我该如何将最近的 N 次提交压缩成一个提交记录?
git rebase
或git merge --squash
。在这个例子中,我们将合并最后3个提交。git reset --soft HEAD~3 &&
git commit
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
git push --force origin myBranch
git rebase --squash-recent
或者甚至是 git commit --amend-many
。 - Adrian Ratnapalabranch@{upstream}
(或者对于当前分支只需使用@{upstream}
;在这两种情况下,最后一部分可以缩写为@{u}
;参见 gitrevisions)。这可能与你的“上次推送的提交”不同(例如,如果其他人推送了建立在你最近推送的提交之上的内容,然后你获取了该内容),但似乎接近你想要的。 - Chris Johnsenpush -f
,但除此之外一切都很好,谢谢。 - 2rs2tsgit push --force
命令来提交并更新该次提交。 - Zach Saucier使用git rebase -i <after-this-commit>
命令,在第二个及后续的提交记录中将"pick"替换成"squash"或"fixup",具体步骤参考手册。
在本例中,<after-this-commit>
可以是SHA1哈希值,也可以是相对于当前分支HEAD位置的相对路径,用于分析rebase命令的提交记录。例如,如果用户想要查看当前HEAD以前5个提交记录,命令为git rebase -i HEAD~5
。
<after-this-commit>
表示提交X+1,即你想压缩的最早提交的父提交。 - joozek你可以使用 git merge --squash
来实现这一点,这比 git rebase -i
稍微更加优雅。假设你在主分支上且想要将最近的12个提交压缩成一个。
警告:首先确保你已提交你的工作——检查 git status
是否干净(因为 git reset --hard
会丢弃已暂存和未暂存的更改)。
然后执行以下操作:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
Git合并文档详细描述了--squash
选项。
更新:相较于Chris Johnsen在他的回答中建议的简单方式git reset --soft HEAD~12 && git commit
,这种方法唯一的优点是您可以获得合并每个提交消息的预填信息。
git merge --squash
更容易。本质上,这种做法的理由是你根本不需要git rebase -i
的“交互性”。 - Mark Longairgit reset --hard
)会触及更多的文件。例如,如果您正在使用Unity3D,则会感激较少的文件被触及。 - cregoxgit merge --squash
在面对移动、删除和重命名时更不容易产生合并冲突,特别是当你从本地分支合并时。(声明:基于仅有的一次经验,如果这在一般情况下不正确,请纠正我!) - CheezmeisterHEAD@ {1}
,只是为了保险起见,例如当您的工作流由于停电等原因被中断一个小时。 - Tobias Kienzler2020年简单的解决方案,无需变基:
git reset --soft HEAD~2
git commit -m "new commit message"
git push -f
push
命令中使用“-f(强制)”选项是一种危险的做法,特别是当你要推送到一个共享版本库(即公共历史记录)时,这会给贡献者带来很多麻烦。 - FXQuantTradergit reset --soft $(git merge-base feature master)
,然后使用git commit
。 - Karl Pokus--force
强制推送。这样做可以让你与团队的其他成员以及不同的远程位置保持一致,因为你知道正在发生什么。而且你还知道历史的哪部分已经稳定了。没有必要把这些隐藏起来。 - hakreforce
推送,并清楚地传达这种方法的影响。强制推送与变基和工作同步紧密相关,因此,在我看来,更多人了解此操作的效果比将其作为外部命令让人们害怕使用要好得多。 - Matheus Felipe我建议尽可能避免使用git reset
,特别是对于Git新手。除非你真的需要基于提交数量自动化一个过程,否则有一种不太复杂的方法...
git merge --squash (工作分支名称)
git commit
提交消息将根据压缩预填充。
gitk
的图形用户界面来标记你要压缩的代码行,并标记要压缩到哪个基础上。在正常情况下,这两个标签已经存在,因此可以跳过第一步。 - Brent Bradburngit branch your-feature && git reset --hard HEAD~N
是最方便的方法。但是,它确实涉及到再次使用 git reset
,而这个答案试图避免这种情况。 - eis感谢 这篇实用的博客文章,我发现你可以使用以下命令将最近的3次提交压缩成一个:
git rebase -i HEAD~3
即使您在本地分支上没有任何跟踪信息或远程库,也很方便使用以下命令:
git rebase -i HEAD~3
将打开交互式变基编辑器,然后可以像正常情况下一样重新排序、压缩、重新命名等操作。
使用交互式变基编辑器:
交互式变基编辑器显示了最近的三个提交。 运行命令git rebase -i HEAD~3
时,此约束由HEAD~3
确定。
最近的提交HEAD
显示在第一行。 以#
开头的行是注释/文档。
显示的文档非常清晰。 在任何给定的行上,您可以从pick
命令更改为其他命令。
我喜欢使用fixup
命令,因为它会将提交的更改“压缩”到上一行的提交中并且丢弃提交的消息。
由于第一行上的提交是HEAD
,在大多数情况下,您会将其保留为pick
。 您不能使用squash
或fixup
,因为没有其他提交可以将其压缩到。
您还可以更改提交的顺序。 这使您可以压缩或修复不按时间顺序相邻的提交。
一个实用的例子
最近我添加了一个新功能。 然后,我修复了两个错误。 但是现在我发现了一个bug(或者只是一个拼写错误)在我添加的新功能中。 多么烦人啊! 我不想让我的提交历史记录被污染!
我首先纠正错误并创建一个新的提交,并注释为squash this into my new feature!
.
然后,我运行git log
或 gitk
并获取新功能的提交SHA(在这种情况下是1ff9460
)。
接下来,我使用git rebase -i 1ff9460~
打开交互式变基编辑器。 在提交SHA之后加上~
告诉编辑器将该提交包含在编辑器中。
接下来,我将包含修复的提交(fe7f1e0
)移动到新功能提交的下面,并将pick
更改为fixup
。
在关闭编辑器时,修复将被压缩到新功能提交中,我的提交历史记录会变得干净整洁!
这在所有提交都是本地时非常有效,但如果您尝试更改已推送到远程的任何提交,则可能会给其他开发人员造成问题!
在bash(或Windows上的Git Bash)中添加全局的“squash”别名。
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
git squash N
... 这会自动将最后的 N
个提交合并在一起。
注意:生成的提交消息是所有合并的提交按顺序组合而成的。如果您对此不满意,您可以随时使用 git commit --amend
手动修改它。(或者,编辑别名以符合您的喜好。)
git squash -m "New summary."
并让 N
自动确定为未推送的提交数量。 - Asclepiusgit commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"
:) - EthanBgit commit --amend
进一步更改提交信息,但这个别名使你能够开始撰写应该包含在提交信息中的良好内容。 - dashesy在您希望合并提交的分支上运行:
git rebase -i HEAD~(n number of commits back to review)
例子:
git rebase -i HEAD~2
如果您想要将这些提交合并在一起,您需要打开文本编辑器,并将每个提交前面的 'pick' 切换为 'squash'。来自文档:
例如,如果您希望将所有提交合并为一个,则 'pick' 是您进行的第一个提交,所有未来的提交(放置在第一个提交下方)都应设置为 'squash'。如果使用vim,请在插入模式下使用:x保存退出编辑器。
然后,继续变基:
git add .
git rebase --continue
查看更多关于重写提交历史的方法和其他信息,请参见这篇有用的文章
--continue
和 vim 的 :x
是什么意思。 - not2qubitgit rebase --continue
来移动到下一个提交并开始合并。:x
是一个命令,当使用vim时保存文件更改,请参见此。 - aabiro要做到这一点,您可以使用以下git命令。
git rebase -i HEAD~n
n(这里等于4)是最后一个提交的编号。然后您将获得以下选项,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
请像下面这样更新:pick
一个提交,将其他提交 squash
到最新的提交中。
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
有关详细信息,请单击链接
git fold --from abc --to efg
这样的命令? - user27182