git 如何压缩两个非连续提交?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3921708/
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
How do I squash two non-consecutive commits?
提问by Nik Reiman
I'm a bit new to the whole rebasing feature within git. Let's say that I made the following commits:
我对 git 中的整个变基功能有点陌生。假设我做了以下提交:
A -> B -> C -> D
Afterwards, I realize that D
contains a fix which depends on some new code added in A
, and that these commits belong together. How do I squash A
& D
together and leave B
& C
alone?
之后,我意识到D
包含一个依赖于在 中添加的一些新代码的修复程序A
,并且这些提交属于一起。如何壁球A
和D
一起休假B
和C
孤独?
回答by Rudi
You can run git rebase --interactive
and reorder D before B and squash D into A.
您可以git rebase --interactive
在 B 之前运行并重新排序 D,并将 D 压缩到 A。
Git will open an editor, and you see a file like this, ex: git rebase --interactive HEAD~4
Git 会打开一个编辑器,你会看到一个这样的文件,例如: git rebase --interactive HEAD~4
pick aaaaaaa Commit A
pick bbbbbbb Commit B
pick ccccccc Commit C
pick ddddddd Commit D
# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Now you change the file that it looks like this:
现在您将文件更改为如下所示:
pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
And git will now meld the changes of A and D together into one commit, and put B and C afterwards. When you don't want to keep the commit message of D, instead of squash
, you would use the fixup
keyword. For more on fixup
, you can consult the git rebase
docs, or check out this questionwhich has some good answers.
git 现在会将 A 和 D 的更改合并到一个提交中,然后将 B 和 C 放在一起。当您不想保留 D 的提交消息时squash
,您可以使用fixup
关键字来代替。有关更多信息fixup
,您可以查阅git rebase
文档,或查看此问题,其中有一些很好的答案。
回答by Nate
Note: You should not change commits that have been pushedto another repo in any way unless you know the consequences.
注意:除非您知道后果,否则您不应以任何方式更改已推送到另一个存储库的提交。
git log --oneline -4
git log --oneline -4
D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
git rebase --interactive
git rebase --interactive
pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
Type i
(Put VIM in insert mode)
类型i
(将 VIM 置于插入模式)
Change the list to look like this (You don't have to remove or include the commit message). Do not misspell squash
!:
将列表更改为如下所示(您不必删除或包含提交消息)。不要拼错squash
!:
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D
Type Escthen ZZ
(Save and exit VIM)
键入Esc然后ZZ
(保存并退出VIM)
# This is a combination of 2 commits.
# The first commit's message is:
commit_message_for_D
# This is the 2nd commit message:
commit_message_for_A
Type i
类型 i
Change the text to what you want the new commit message to look like. I recommend this be a description of the changes in commit A
and D
:
将文本更改为您希望新提交消息的外观。我建议这是对 commitA
和更改的描述D
:
new_commit_message_for_A_and_D
Type Escthen ZZ
键入Esc然后ZZ
git log --oneline -4
git log --oneline -4
E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B
git show E
git show E
(You should see a diff showing a combination of changes from A and D)
You have now created a new commit E
. Commits A
and D
are no longer in your history but are not gone. You can still recover them at this point and for a while by git rebase --hard D
(git rebase --hard
will destroy any local changes!).
您现在已经创建了一个新的提交E
。提交A
并且D
不再在您的历史记录中,但并没有消失。此时您仍然可以恢复它们,一段时间后git rebase --hard D
(git rebase --hard
将破坏任何本地更改!)。
回答by Adam Johns
For those using SourceTree:
对于那些使用SourceTree 的人:
Make sure you haven't already pushed the commits.
确保您尚未推送提交。
- Repository > Interactive Rebase...
- Drag D (the newer commit) to be directly above A (the older commit)
- Make sure commit D is highlighted
- Click
Squash with previous
- 存储库 > 交互式变基...
- 将 D(较新的提交)拖到 A(较旧的提交)正上方
- 确保提交 D 突出显示
- 点击
Squash with previous
回答by Oleksiy Guzenko
Interactive rebase works well until you have big feature branch with 20-30 commits and/or couple of merges from master or/and fixing conflicts while you was commiting in your branch. Even with finding my commits through history and replacing pick
with squash
doesn't worked here. So i was looking for another way and found this article.
I did my changes to work this on separate branch:
交互式 rebase 运行良好,直到您在分支中提交时拥有具有 20-30 次提交和/或来自 master 的合并或/和修复冲突的大功能分支。即使通过历史找到我的提交并替换pick
为squash
在这里也不起作用。所以我正在寻找另一种方式并找到了这篇文章。我做了我的更改以在单独的分支上工作:
git checkout master
git fetch
git pull
git merge branch-name
git reset origin/master
git branch -D branch-name
git checkout -b branch-name
git add --all
#Do some commit
git push -f --set-upstream origin branch-name
Before this I got my pull request with about ~30 commits with 2-3 merges from master + fixing conflicts. And after this I got clear PR with one commit.
在此之前,我收到了大约 30 次提交的拉取请求,其中包含 2-3 次来自 master + 修复冲突的合并。在此之后,我通过一次提交获得了明确的 PR。
P.S. here is bash scriptto do this steps in automode.
PS 这里是 bash脚本,用于在自动模式下执行此步骤。
回答by Cotton
$ git checkout master
$ git checkout master
$ git log --oneline
$ git log --oneline
D
C
B
A
$ git rebase --onto HEAD^^^ HEAD^
$ git rebase --onto HEAD^^^ HEAD^
$ git log --oneline
$ git log --oneline
D
A