清理 Git 中的分支历史记录

4
我已经在一个特性分支上工作好几天了。在这段时间里,我犯了很多错误并提交了很多不必要的代码更改,接着又不得不在下一次提交中将它们撤消。
最终,我找到了最佳解决方案,现在我准备创建一个拉取请求(Pull-Request)。然而,我不希望每个人都能看到我在分支上做了多少愚蠢的提交。 :-)
那么,创建一个干净的PR并包含最新的代码但不包括所有这些提交的最佳方法是什么?
我正在使用 Git 终端。

将所有提交压缩成一个,使用 git rebase interactive 命令。 - u_mulder
4
可能是Squash my last X commits together using Git的重复问题。 - u_mulder
2个回答

5
您可以运行交互式的 git rebase:
git rebase -i HEAD~N

其中 N 代表你想对历史记录中最后 N 次提交执行操作(例如修改提交信息、删除提交等)。

这个命令允许你选择一系列的操作并应用到每一个提交(最多到第 N 个提交)。你可以在这里找到更多有关可用操作的信息。


4
如果您从未推送过该分支,则可以进行交互式变基来“压缩”不需要的提交,而不会出现任何问题。 如果您曾经推送该分支,则进行变基将需要您“强制推送”该分支,这可能是一个问题或不是问题。
如果远程配置为禁止强制推送,则强制推送是个问题。 如果遇到这种情况,则您无法做太多事情。
如果其他用户可能在他们的副本中拥有分支的副本,特别是如果他们可能以此为基础进行工作,则强制推送可能会成为问题。 在这种情况下,您必须与其他用户协调;请参阅“从上游变基中恢复”的git rebase文档获取更多信息。https://git-scm.com/docs/git-rebase 因此,如果以上内容阻止您进行变基,则没有太多事情可做,您只需将“不想让人看到错误”这个虚荣心放在一边。(但是反过来说,如果您曾经推送过该分支,则其他人已经可以看到您所做的了。)
因此,如果要继续进行变基:
假设您从master创建了您的特性分支,则可以说
git rebase -i master feature

如果您希望将分支移动到当前主分支顶端(集成master的更改),或者

git rebase -i $(git merge-base master feature) feature

使重写的分支基于您的分支所在的位置。

这将打开一个文本编辑器,其中包含给出rebase指令的“TODO列表”。每行代表一个提交。对于要删除的每个提交,在列表中找到该提交,然后将下一个提交行的第一个单词更改为“squash”。

例如,如果TODO列表显示:

pick 1111111 a good commit
pick 2222222 a bad commit
pick 3333333 revert the bad commit
pick 4444444 another good commit

如果您只想保留1111111和4444444,您需要编辑列表

pick 1111111 a good commit
pick 2222222 a bad commit
squash 3333333 revert the bad commit
squash 4444444 another good commit

这将前面的三个提交(2)合并到一起,然后将第四个提交合并到前面的提交中(即将2和3合并的结果),因此您将只剩下1和4。(2和3的更改仍然包括在内,但如果3真正撤销了2,则意味着没有任何变化。)

分支已经推送,但没有其他人使用过它。我可以直接删除远程分支,将本地分支变基并再次推送吗? - user1941537
@user1941537 - 这样做的后果与强制推送的后果完全相同。这样做的唯一原因是为了规避访问控制(如果您有删除分支的访问权限但没有强制推送的访问权限)。如果我管理一个仓库,有人这样做了,我会把它看作是提醒我,如果我没有给他们强制推送的访问权限,我也不应该给他们删除的权限,并相应地调整权限。所以如果我们把这种博弈行为排除在外:你可以这样做,但为什么呢? - Mark Adelsberger
我无法强制推送。 - user1941537

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接