将旧的git历史记录合并到初始提交中

时间:2013-09-16 08:47:27

标签: git

虽然有几个主题涉及类似的问题,但我似乎无法用Git rebase解决的问题解决这个问题。

我有一个非常大的Git回购,我想切断提交历史的主要部分。提交图的当前状态如下:

(huge tree of various branching and merging) -> commit_I_want_to_squash_to -> branching off into master and couple of feature branches

我想要的结果是:

commit_I_want_to_squash_to_is_first_in_tree -> branching off into master and couple of feature branches

我想这应该是可能的,因为所有当前分支都使用单个提交作为原点。我尝试使用git rebase --squash,但似乎要压缩300多个分支历史是一项相当大的任务。应该以某种方式选择在我想要作为第一个提交之前“切片”提交树。

3 个答案:

答案 0 :(得分:4)

基本上你想要做的就是在某个提交之前切断历史。在Git术语中,这意味着您希望重写该提交,从父级到没有父级(作为新历史的开始提交)。

这可以使用git filter-branch完成,如下所示:

git filter-branch \
  --parent-filter 'test $GIT_COMMIT = <initial-commit-id> && echo "" || cat' \
  --tag-name-filter cat -- --all

另一种选择是使用移植物功能如下。请注意,您可以使用git log或图形查看器检查第一个命令后生成的历史记录,以验证所需结果是否正确:

echo "<initial-commit-id> " >> info/grafts  # .git/info/grafts in non-bare repo
git filter-branch --tag-name-filter cat -- --all

确保在使用--mirror克隆的新裸仓库中执行上述命令。这样可以更轻松地推送所有更新的分支和标签。

不包含上述initial-commit-id的旧标记/分支仍将指向旧历史记录。您将不得不删除它们以真正摆脱旧的历史。您应该可以使用git branch --contains <previous-initial-commit-id>git tag --contains <previous-initial-commit-id>找到它们。 <previous-initial-commit-id>是先前“初始提交”的ID,重写的历史记录不再引用该ID。

完成上述所有操作后,请参阅Checklist for Shrinking a Repository了解如何彻底摆脱旧历史。

答案 1 :(得分:0)

如果我必须这样做,我会写:

git rebase -i <initialCommitOfTheTree>

按照您的意愿压制所有提交。是的,如果你需要编辑300行,这是非常难的工作,但是你可以快速解析它在vim或其他文本编辑器上,并用s替换你想要改变的所有行的开头。

就像@mnagel所说,你应该有一个很好的理由。

干杯。

的Vitor。

答案 2 :(得分:0)

取决于您的仓库,启动新仓库可能是可行的,从那里的“新初始提交”中复制文件并使其成为新的提交。然后将现有的repo添加为远程和cherrypick所有后来的提交到您的新repo。如果你在“新的初始提交”之后有线性历史记录,这应该相当顺利。

也许重新定位提交(而不是樱桃)可以使用更复杂的布局,但我不会做很多,所以我不想在这里提出建议。