Git:使用相同的消息和时间重写历史记录以折叠提交(合并子模块)

时间:2013-07-02 21:34:07

标签: git mercurial

我们正在开展一个庞大的项目。在开发之初,我们决定使用 Mercurial 和子库存功能。经过2年的开发,我们有10个独立的模块,每个模块都有一个存储库。我们发现,子存储库不是我们的最佳解决方案,并且发现 Git 对我们来说比 Mercurial 更好。

所以,我们希望: 1.将mercurial子存储库加入一个 Main mercurial存储库,同时保留完整的历史记录 2.将此存储库转换为 Git 存储库(同时保留历史记录)

已经完成了第一步(在stackoverflow上有一个很好的答案),为每个子存储库使用hg-convert扩展并将它们合并为一个。

第二步也是使用快速导出/ hg-fast-export工具完成的。而且......一切都很好,除了一件事。由于Mercurial与子存储库具有使用一个命令提交所有子存储库的功能,因此我们经常使用它。现在历史看起来像这样:

commit c6a33eb195c574cfa81469f2109c0840852a5571
Author: John
Date:   Mon Jul 1 20:26:14 2013 +0200

Add another one feature

commit fc5390a726847ef2971edd591020c5c1d2aa168b
Author: John
Date:   Mon Jul 1 20:26:14 2013 +0200

Add another one feature

commit 2477c27b361657dabeb28802f5f510f170378fc0
Author: John
Date:   Mon Jul 1 20:26:14 2013 +0200

Add another one feature

原因是这些提交中的每一个都来自不同的原始子库。我们的历史树看起来像这样:

subrepo_1/master: -A-B-C-D-E--EJ---EJM---merged---->
                              /     /
subrepo_2/master: -F-G-H-I-J--     /
                                  /
subrepo_3/master: -K-----L-M------

因此,来自不同子模块的主分支完全分离。如果我结帐,例如提交 F 然后工作目录不包含来自* subrepo_1 *和* subrepo_3 *的任何代码。

我们希望只有一个主分支,它应该是这样的:

master: -AFK-BGK-CHK-DIL-EJM----->

因此,一个提交应代表几个模块中的分组更改。

问题:

  1. 是否可以通过任何一个使用 Git 的命令将历史记录中的每组提交折叠为一个?这些提交具有相同的时间,消息和作者。

    注意:“git rebase -i”似乎不是一个解决方案,因为我们有太多的提交手动压缩。

  2. 如果无法使用一个 Git 命令,那么是否可以根据少量 Git 命令编写脚本?

  3. 我的想法(感谢@Chronial回复)是:收集所有主分支的提交列表并按时间排序,从列表中挑选每个提交到新的干净分支。然后使用带有commit-filter的filter-branch以相同的时间/消息过滤每组提交,只留下一个。可以吗?

  4. 提前致谢。

2 个答案:

答案 0 :(得分:0)

解决方案之前的第一个问题:这10个模块有多大? Git对于一个巨大的存储库来说并不是那么好。相反,建议是完全按照您现在的方案执行:许多子模块。在完成迁移之前考虑一下。请参阅此讨论:http://comments.gmane.org/gmane.comp.version-control.git/189776

关于您的问题:

  1. 我认为可以使用 - autosquash 参数。请参阅:http://mcpierce.blogspot.com.br/2012/08/git-fixup-and-autosquash.html

答案 1 :(得分:0)

没有单一命令。您需要将filter-branchcommit-filter一起使用。以下是您需要的部分:

  1. 运行git log -1 --pretty=format:'%H %ct %P' --full-history --all以获取可解析的提交列表,时间戳及其父母。
  2. 编写一个脚本,找到同时非合并提交字符串的 last :对于每次提交,检查其父级是否具有相同的时间戳并且不合并(=只有一个父母自己)。如果是这样,请将其添加到“删除”列表中。
  3. 您的提交过滤器将获取提交的shas及其父提交(请参阅git help filter-branch)。从(2)开始,您应该将所需的所有信息存储在某处。只保留同一时间提交字符串的最后,通过为所有其他提交调用skip_commit,为要保留的那些调用git commit-tree(无参数)。
  4. 我会忽略合并,因为它们使事情变得复杂,我假设你真的没有合并的问题吗?