虽然有几个主题涉及类似的问题,但我似乎无法用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多个分支历史是一项相当大的任务。应该以某种方式选择在我想要作为第一个提交之前“切片”提交树。
答案 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。如果你在“新的初始提交”之后有线性历史记录,这应该相当顺利。
也许重新定位提交(而不是樱桃)可以使用更复杂的布局,但我不会做很多,所以我不想在这里提出建议。