我对git中的整个重新定位功能有些陌生。假设我做了以下提交:
A -> B -> C -> D
之后,我意识到其中D
包含一个修复程序,该修复程序依赖于中添加的一些新代码A
,并且这些提交属于一起。如何壁球A
和D
一起休假B
和C
孤独?
我对git中的整个重新定位功能有些陌生。假设我做了以下提交:
A -> B -> C -> D
之后,我意识到其中D
包含一个修复程序,该修复程序依赖于中添加的一些新代码A
,并且这些提交属于一起。如何壁球A
和D
一起休假B
和C
孤独?
Answers:
您可以先运行git rebase --interactive
D并对其重新排序,然后再将D压缩到A中。
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
现在,您更改文件,如下所示:
pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
git现在将A和D的更改合并到一个提交中,然后将B和C放入。当您不想保留D的提交消息时squash
,可以使用fixup
关键字而不是。有关更多信息fixup
,您可以查阅git rebase
文档,或查看该问题有一些不错的答案。
注意:除非您知道后果,否则不应以任何方式更改已推送到另一个存储库的提交。
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
将文本更改为新提交消息的外观。我建议这是对commit 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次提交的大型功能分支和/或主分支中的几次合并或/和在分支中提交时解决冲突为止。即使通过历史查找我的提交并替换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
在此之前,我收到了大约30次提交的请求请求,其中有2-3次来自主服务器+修复冲突。在此之后,我一次提交就获得了明确的PR。
PS这里是bash 脚本,可以在自动模式下执行此步骤。
$ git checkout master
$ git log --oneline
D
C
B
A
$ git rebase --onto HEAD ^^^ HEAD ^
$ git log --oneline
D
A
--oneline
?好像您已删除C
和B
,这不是OP想要的。
git show A
),并且D,C和B在我的参考日志中丢失了。不得不git rebase D
回来。