Git 如何挤压两个不连续的提交?

Git 如何挤压两个不连续的提交?,git,git-rebase,Git,Git Rebase,我对git中的整个重定基调功能有点陌生。假设我做出了以下承诺: A -> B -> C -> D 之后,我意识到D包含一个修复,该修复依赖于a中添加的一些新代码,并且这些提交属于一个整体。如何将A和D挤压在一起,而将B和C单独留在一起?您可以运行git rebase--interactive并在B之前重新排序D,然后将D挤压到A中 Git将打开一个编辑器,您会看到这样一个文件,例如:Git rebase——interactive HEAD~4 pick aaaaaaa Com

我对git中的整个重定基调功能有点陌生。假设我做出了以下承诺:

A -> B -> C -> D

之后,我意识到
D
包含一个修复,该修复依赖于
a
中添加的一些新代码,并且这些提交属于一个整体。如何将
A
D
挤压在一起,而将
B
C
单独留在一起?

您可以运行
git rebase--interactive
并在B之前重新排序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的提交消息时,可以使用
fixup
关键字,而不是
squash
。有关
fixup
的更多信息,您可以咨询,或查看有一些好答案的。

$git checkout master

$git日志--一行

$git rebase--在头部^^^头部^

$git日志--一行


注意:除非您知道原因,否则您不应以任何方式更改已推送到另一回购协议的提交

git日志--oneline-4

D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B
git-rebase——交互式

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
!:

然后键入Esc
ZZ
(保存并退出VIM)

类型
i

将文本更改为新提交消息的外观。我建议这是对提交
a
D
中的更改的描述:

new_commit_message_for_A_and_D
然后键入Esc
ZZ

git日志--oneline-4

D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
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 D
恢复它们(git-rebase--hard
将破坏任何本地更改!)。

对于那些使用:

确保您尚未推送提交

  • 存储库>交互式重基…
  • 将D(较新的提交)拖动到A(较旧的提交)的正上方
  • 确保提交D突出显示
  • 单击
    Squash与上一个

  • 交互式重基工作得很好,直到你有了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
    
    在此之前,我收到了来自master的约30次提交和2-3次合并的pull请求,并修复了冲突。在这之后,我通过一次承诺获得了清晰的公共关系


    这里是bash在自动模式下执行这些步骤。

    我想你的意思是
    --oneline
    ?看起来你已经放弃了
    C
    B
    ,这不是OP的意图。对我来说不起作用。它将我的头和主机都移动到A,但没有将D合并到A(
    git show A
    ),并且D、C和B在我的ref日志中丢失。必须
    git-rebase-D
    才能返回。最初,我将其理解为“将D重基到A上,将D挤压到A上,然后将B重基到DA上”。答案中不清楚这是否可以通过在文本编辑器中重新排序行来完成。如果您的分支是本地分支,则在重定基址时,您将获得当前分支的
    无跟踪信息。在这种情况下,您需要指定要处理的提交数量,如下所示:
    git-rebase-i HEAD~4
    。看,我使用交互模式(git rebase-I)多年了,我刚刚意识到它可以重新排序。感谢大家用粗体告诉所有刚接触git的人。没有人告诉我在rebase中重新排序会产生奇迹。文章中的第一个解决方案非常好,谢谢链接
    (You should see a diff showing a combination of changes from A and D)
    
    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