2

尽管有几个主题涵盖了类似的问题,但我似乎无法通过应该解决的问题来解决这个问题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 多个分支历史是一项相当大的任务。应该有一个选项可以在我想作为第一个提交之前“切片”提交树。

4

3 回答 3

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>and找到它们git tag --contains <previous-initial-commit-id><previous-initial-commit-id>是前一个“初始提交”的 ID,重写的历史不再引用它。

完成上述所有操作后,请参阅缩减存储库的清单以了解如何完全摆脱旧历史。

于 2013-09-16T10:34:16.063 回答
0

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

git rebase -i <initialCommitOfTheTree>

根据需要压缩所有提交。是的,如果您必须编辑 300 行,这将非常辛苦,但是您可以在 vim 或其他文本编辑器上快速解析它,并将您想要更改的所有行的开头替换为s.

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

干杯。

维托。

于 2013-09-16T09:09:02.417 回答
0

根据您的存储库,开始一个新的存储库可能是可行的,从那里的“新初始提交”复制文件并使其成为新提交。然后将现有的 repo 添加为远程并将所有以后的提交cherrypick 到您的新 repo 中。如果您在“新的初始提交”之后有线性历史记录,这应该工作得相当顺利。

也许重新提交提交(而不是cherrypicking)对于更复杂的布局可以正常工作,但我不经常这样做,所以我不想在这里提出建议。

于 2013-09-16T10:28:38.357 回答