如何压缩两个非连续提交?

Nik*_*man 156 git git-rebase

我对git中的整个rebasing功能有点新意.假设我做了以下提交:

A -> B -> C -> D
Run Code Online (Sandbox Code Playgroud)

之后,我意识到D包含一个修复程序,它依赖于添加的一些新代码A,并且这些提交属于一起.如何壁球AD在一起,离开BC一个人吗?

Rud*_*udi 218

你可以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
Run Code Online (Sandbox Code Playgroud)

现在您更改它看起来像这样的文件:

pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
Run Code Online (Sandbox Code Playgroud)

然后git将A和D的变化合并为一个提交,然后将B和C放在一起.如果您不想保留D的提交消息,也可以使用"fix"关键字.

  • 最初,我把它读作"将A反射到A上,将D压入A,然后将B重新粘贴到DA上".从答案中可以看出,这可以通过在文本编辑器中重新排序来完成. (5认同)
  • 如果您的分支机构是本地分支机构,则在重新定基时将收到“当前分支机构没有跟踪信息”错误。在这种情况下,您需要指定要使用的提交数,例如:git rebase -i HEAD〜4。参见[此答案](/sf/answers/2854930501/)。 (2认同)
  • 我使用交互模式(git rebase -i)多年,我刚刚意识到它可以**重新排序**。谢谢 (2认同)

Nat*_*ate 41

注意:除非您知道后果,否则不应以任何方式更改已推送到其他仓库的提交.

git log --oneline -4

D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

键入i(将VIM置于插入模式)

将列表更改为如下所示(您不必删除或包含提交消息).不要拼错squash!:

pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

类型 i

将文本更改为您希望新提交消息的样子.我建议这是对提交中的更改的描述,A并且D:

new_commit_message_for_A_and_D
Run Code Online (Sandbox Code Playgroud)

Esc然后键入ZZ

git log --oneline -4

E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B
Run Code Online (Sandbox Code Playgroud)

git show E

(You should see a diff showing a combination of changes from A and D)
Run Code Online (Sandbox Code Playgroud)

您现在已经创建了一个新提交E.提交A并且D不再在您的历史中,但不会消失.您仍然可以在此时恢复它们一段时间git rebase --hard D(git rebase --hard将破坏任何本地更改!).


Ada*_*hns 5

对于那些使用SourceTree的人:

确保您尚未推送提交。

  1. 存储库 > 交互式变基...
  2. 将 D(较新的提交)拖动到 A(较旧的提交)的正上方
  3. 确保突出显示提交 D
  4. 点击Squash with previous