使用 Git 压缩我最后的 X 提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5189560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Squash my last X commits together using Git
提问by markdorison
How can I squash my last X commits together into one commit using Git?
如何使用 Git 将我最后的 X 次提交合并为一次提交?
采纳答案by Anomie
Use git rebase -i <after-this-commit>
and replace "pick" on the second and subsequent commits with "squash" or "fixup", as described in the manual.
git rebase -i <after-this-commit>
在第二次和后续提交中使用“pick”并将其替换为“squash”或“fixup”,如手册中所述。
In this example, <after-this-commit>
is either the SHA1 hash or the relative location from the HEAD of the current branch from which commits are analyzed for the rebase command. For example, if the user wishes to view 5 commits from the current HEAD in the past the command is git rebase -i HEAD~5
.
在此示例中,<after-this-commit>
是 SHA1 哈希或来自当前分支的 HEAD 的相对位置,从该位置分析 rebase 命令的提交。例如,如果用户希望查看过去当前 HEAD 的 5 次提交,则命令为git rebase -i HEAD~5
.
回答by Chris Johnsen
You can do this fairly easily without git rebase
or git merge --squash
. In this example, we'll squash the last 3 commits.
无需git rebase
或即可轻松完成此操作git merge --squash
。在这个例子中,我们将压缩最后 3 次提交。
If you want to write the new commit message from scratch, this suffices:
如果你想从头开始编写新的提交消息,这就足够了:
git reset --soft HEAD~3 &&
git commit
If you want to start editing the new commit message with a concatenation of the existing commit messages (i.e. similar to what a pick/squash/squash/…/squash git rebase -i
instruction list would start you with), then you need to extract those messages and pass them to git commit
:
如果你想用现有提交消息的串联开始编辑新的提交消息(即类似于 pick/squash/squash/.../squashgit rebase -i
指令列表将开始你的内容),那么你需要提取这些消息并通过他们git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
Both of those methods squash the last three commits into a single new commit in the same way. The soft reset just re-points HEAD to the last commit that you do not want to squash. Neither the index nor the working tree are touched by the soft reset, leaving the index in the desired state for your new commit (i.e. it already has all the changes from the commits that you are about to “throw away”).
这两种方法都以相同的方式将最后三个提交压缩为一个新提交。软重置只是将 HEAD 重新指向您不想压缩的最后一次提交。索引和工作树都不会被软重置触及,使索引处于新提交所需的状态(即,它已经拥有您将要“丢弃”的提交的所有更改)。
回答by Mark Longair
You can use git merge --squash
for this, which is slightly more elegant than git rebase -i
. Suppose you're on master and you want to squash the last 12 commits into one.
您可以git merge --squash
为此使用它,它比git rebase -i
. 假设您在 master 上,并且想要将最后 12 个提交压缩为一个。
WARNING: First make sure you commit your work—check that git status
is clean (since git reset --hard
will throw away staged and unstaged changes)
警告:首先确保你提交了你的工作——检查它git status
是否干净(因为git reset --hard
会丢弃已暂存和未暂存的更改)
Then:
然后:
# 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
The documentation for git merge
describes the --squash
option in more detail.
的文档git merge
--squash
更详细地描述了该选项。
Update:the only real advantage of this method over the simpler git reset --soft HEAD~12 && git commit
suggested by Chris Johnsen in his answeris that you get the commit message prepopulated with every commit message that you're squashing.
更新:与git reset --soft HEAD~12 && git commit
Chris Johnsen 在他的回答中建议的更简单的方法相比,此方法的唯一真正优势是,您将获得预填充了您正在压缩的每条提交消息的提交消息。
回答by nobar
I recommend avoiding git reset
when possible -- especially for Git-novices. Unless you really need to automate a process based on a numberof commits, there is a less exotic way...
我建议git reset
尽可能避免——尤其是对于 Git 新手。除非你真的需要基于多次提交来自动化一个过程,否则还有一种不太奇特的方式......
- Put the to-be-squashed commits on a working branch (if they aren't already) -- use gitk for this
- Check out the target branch (e.g. 'master')
git merge --squash (working branch name)
git commit
- 将要压缩的提交放在一个工作分支上(如果它们还没有)——为此使用 gitk
- 检查目标分支(例如'master')
git merge --squash (working branch name)
git commit
The commit message will be prepopulated based on the squash.
提交消息将根据壁球预先填充。
回答by EthanB
Based on Chris Johnsen's answer,
根据克里斯约翰森的回答,
Add a global "squash" alias from bash: (or Git Bash on Windows)
从 bash 添加全局“壁球”别名:(或 Windows 上的 Git Bash)
git config --global alias.squash '!f(){ git reset --soft HEAD~ && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... or using Windows' Command Prompt:
...或使用 Windows 的命令提示符:
git config --global alias.squash "!f(){ git reset --soft HEAD~ && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Your ~/.gitconfig
should now contain this alias:
你~/.gitconfig
现在应该包含这个别名:
[alias]
squash = "!f(){ git reset --soft HEAD~ && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Usage:
用法:
git squash N
... Which automatically squashes together the last N
commits, inclusive.
...这会自动将最后一次N
提交压缩在一起,包括在内。
Note: The resultant commit message is a combination of all the squashed commits, in order. If you are unhappy with that, you can always git commit --amend
to modify it manually. (Or, edit the alias to match your tastes.)
注意:生成的提交消息是所有压缩提交的组合,按顺序排列。如果您对此不满意,您可以随时git commit --amend
手动修改它。(或者,编辑别名以符合您的口味。)
回答by br3nt
Thanks to this handy blog postI found that you can use this command to squash the last 3 commits:
感谢这篇方便的博客文章,我发现你可以使用这个命令来压缩最后 3 个提交:
git rebase -i HEAD~3
This is handy as it works even when you are on a local branch with no tracking information/remote repo.
这很方便,因为即使您在没有跟踪信息/远程仓库的本地分支上也能工作。
The command will open the interactive rebase editor which then allows you to reorder, squash, reword, etc as per normal.
该命令将打开交互式 rebase 编辑器,然后允许您按照正常方式重新排序、压缩、改写等。
Using the interactive rebase editor:
使用交互式变基编辑器:
The interactive rebase editor shows the last three commits. This constraint was determined by HEAD~3
when running the command git rebase -i HEAD~3
.
交互式 rebase 编辑器显示最后三个提交。此约束由HEAD~3
运行命令时确定git rebase -i HEAD~3
。
The most recent commit, HEAD
, is displayed first on line 1. The lines starting with a #
are comments/documentation.
最近的提交,HEAD
首先显示在第 1 行。以 a 开头的行#
是注释/文档。
The documentation displayed is pretty clear. On any given line you can change the command from pick
to a command of your choice.
显示的文档非常清楚。在任何给定的行上,您都可以将命令更改pick
为您选择的命令。
I prefer to use the command fixup
as this "squashes" the commit's changes into the commit on the line above and discards the commit's message.
我更喜欢使用该命令,fixup
因为它会将提交的更改“压缩”到上一行的提交中,并丢弃提交的消息。
As the commit on line 1 is HEAD
, in most cases you would leave this as pick
.
You cannot use squash
or fixup
as there is no other commit to squash the commit into.
由于第 1 行的提交是HEAD
,因此在大多数情况下,您会将其保留为pick
. 您不能使用squash
orfixup
因为没有其他提交可以压缩提交。
You may also change the order of the commits. This allows you to squash or fixup commits that are not adjacent chronologically.
您还可以更改提交的顺序。这允许您压缩或修复按时间顺序不相邻的提交。
A practical everyday example
一个实际的日常例子
I've recently committed a new feature. Since then, I have committed two bug fixes. But now I have discovered a bug (or maybe just a spelling error) in the new feature I committed. How annoying! I don't want a new commit polluting my commit history!
我最近提交了一个新功能。从那时起,我已经修复了两个错误。但是现在我在我提交的新功能中发现了一个错误(或者可能只是一个拼写错误)。好烦啊!我不希望新的提交污染我的提交历史!
The first thing I do is fix the mistake and make a new commit with the comment squash this into my new feature!
.
我做的第一件事是修复错误并使用评论进行新的提交squash this into my new feature!
。
I then run git log
or gitk
and get the commit SHA of the new feature (in this case 1ff9460
).
然后我运行git log
orgitk
并获取新功能的提交 SHA(在本例中1ff9460
)。
Next, I bring up the interactive rebase editor with git rebase -i 1ff9460~
. The ~
after the commit SHA tells the editor to include that commit in the editor.
接下来,我使用git rebase -i 1ff9460~
. 在~
后提交SHA告诉编辑器,包括编辑,就提交。
Next, I move the commit containing the fix (fe7f1e0
) to underneath the feature commit, and change pick
to fixup
.
接下来,我将包含修复 ( fe7f1e0
)的提交移动到功能提交下方,并更改pick
为fixup
.
When closing the editor, the fix will get squashed into the feature commit and my commit history will look nice and clean!
关闭编辑器时,修复将被压缩到功能提交中,我的提交历史将看起来干净整洁!
This works well when all the commits are local, but if you try to change any commits already pushed to the remote you can really cause problems for other devs that have checked out the same branch!
当所有提交都是本地的时,这很有效,但是如果您尝试更改已推送到远程的任何提交,您真的会给其他已签出同一分支的开发人员带来问题!
回答by Matthias M
If you use TortoiseGit, you can the function Combine to one commit
:
如果您使用 TortoiseGit,您可以使用以下功能Combine to one commit
:
- Open TortoiseGit context menu
- Select
Show Log
- Mark the relevant commits in the log view
- Select
Combine to one commit
from the context menu
- 打开 TortoiseGit 上下文菜单
- 选择
Show Log
- 在日志视图中标记相关提交
- 选择
Combine to one commit
从上下文菜单
This function automatically executes all necessary single git steps. Unfortunatly only available for Windows.
这个函数会自动执行所有必要的单个 git 步骤。不幸的是,仅适用于 Windows。
回答by Jakir Hosen Khan
To do this you can use following git command.
为此,您可以使用以下 git 命令。
git rebase -i HEAD~n
n(=4 here) is the number of last commit. Then you got following options,
n(=4 here) 是最后一次提交的次数。然后你有以下选项,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Update like below pick
one commit and squash
the others into the most recent,
像下面的pick
一个提交和squash
其他提交一样更新到最新的,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
For details click on the Link
详情请点击链接
回答by trudolf
Based on this articleI found this method easier for my usecase.
基于这篇文章,我发现这种方法更适合我的用例。
My 'dev' branch was ahead of 'origin/dev' by 96 commits (so these commits were not pushed to the remote yet).
我的 'dev' 分支领先于 'origin/dev' 96 次提交(因此这些提交尚未推送到远程)。
I wanted to squash these commits into one before pushing the change. I prefere to reset the branch to the state of 'origin/dev' (this will leave all changes from the 96 commits unstaged) and then commit the changes at once:
我想在推动更改之前将这些提交合并为一个。我更喜欢将分支重置为 'origin/dev' 状态(这将使 96 次提交的所有更改保持未暂存状态),然后立即提交更改:
git reset origin/dev
git add --all
git commit -m 'my commit message'
回答by aabiro
In the branch you would like to combine the commits on, run:
在您想要合并提交的分支中,运行:
git rebase -i HEAD~(n number of commits back to review)
example:
例子:
git rebase -i HEAD~1
This will open the text editor and you must switch the 'pick' in front of each commit with 'squash' if you would like these commits to be merged together. From documentation:
这将打开文本编辑器,如果您希望将这些提交合并在一起,则必须将每个提交前面的“pick”切换为“squash”。从文档:
p, pick = use commit
p, 选择 = 使用提交
s, squash = use commit, but meld into previous commit
s, squash = 使用提交,但融合到之前的提交中
For example, if you are looking to merge all the commits into one, the 'pick' is the first commit you made and all future ones (placed below the first) should be set to 'squash'. If using vim, use :xin insert mode to save and exit the editor.
例如,如果您希望将所有提交合并为一个,“pick”是您所做的第一个提交,并且所有未来的提交(放置在第一个下方)应设置为“squash”。如果使用 vim,请在插入模式下使用:x保存并退出编辑器。
Then to continue the rebase:
然后继续rebase:
git rebase --continue
For more on this and other ways to rewrite your commit history see this helpful post