我对git中的整个rebasing功能有点新意。假设我做了以下提交:
A -> B -> C -> D
之后,我意识到D
包含一个修复,它取决于A
中添加的一些新代码,并且这些提交属于一起。我如何将A
和D
压在一起并单独留下B
和C
?
您可以运行git rebase --interactive
并在B之前重新排序D并将D压入A.
Git会打开一个编辑器,你会看到一个这样的文件:
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
现在您更改它看起来像这样的文件:
pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
然后git将A和D的变化合并为一个提交,然后将B和C放在一起。如果您不想保留D的提交消息,也可以使用“fix”关键字。
注意:除非您知道consequences,否则不应以任何方式更改已推送到其他仓库的提交。
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
pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
输入i
(将VIM置于插入模式)
将列表更改为如下所示(您不必删除或包含提交消息)。不要拼错squash
!:
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D
输入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
输入i
将文本更改为您希望新提交消息的样子。我建议这是对提交A
和D
中的更改的描述:
new_commit_message_for_A_and_D
键入Esc然后ZZ
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
(You should see a diff showing a combination of changes from A and D)
您现在已经创建了一个新的提交E
。提交A
和D
不再是你的历史,但没有消失。你现在仍然可以通过git rebase --hard D
恢复它们一段时间(git rebase --hard
会破坏任何局部变化!)。
对于那些使用SourceTree:
确保您尚未推送提交。
Squash with previous
交互式rebase运行良好,直到你有大型功能分支,20-30次提交和/或几次合并来自master或/和修复冲突,而你在你的分支机构提交。即使通过历史找到我的提交并用pick
替换squash
也不起作用。所以我正在寻找另一种方式,发现这个article。我做了我的更改,在另一个分支上工作:
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
在此之前,我得到了大约30次提交的拉取请求,其中2-3次合并来自主人+修复冲突。在此之后我通过一次提交获得了明确的PR。
附:这里是bash script在automode中执行此步骤。
$ git checkout master
$ git log --oneline
D
C
B
A
$ git rebase --onto HEAD ^^^ HEAD ^
$ git log --oneline
D
A