“这是可能的,甚至很容易。Git有很多不同的方法来实现它。”
“按照你最初建议的字面意思:”
“......在变基之前压缩测试分支上的所有提交”
“如果您在分支master上运行git merge之前进行操作,那么这将是最简单的方法。(我知道您没有将git merge列为命令,但是在您的第6步中运行了git merge:”
“因为git pull只是git fetch后跟git merge。) 但是在之后做这件事还是相当容易的; 我们只需要针对正确的提交ID进行操作。”
“让我们画出您在第4步的提交图形:”
...<- o <- * <
\
A <- B <
这幅图表明有两个标签
1指向我标记为
*
的提交,即
master
和
origin/master
。提交
*
回指到提交
o
,它又指回更多的提交:这就是分支
master
的历史。
你创建的分支的标签(现在你正在该分支上,因此有
HEAD=
部分)指向提交
B
。提交
B
然后指向提交
A
,它再指向提交
*
。这就是分支
test-branch
的历史:你在
*
处创建了它,然后添加了
A
,再添加了
B
。
以下是两种简单合并提交
A
和
B
的方法:
git rebase -i master
这将为您提供一个交互式编辑会话,您可以在其中“选择”第一个提交,然后“压缩”第二个提交,并将两个提交消息汇集在一起,并让您按照通常的方式编辑结果。然后它将创建一个(单一的)新提交,其树是提交B
的树。
git reset --soft master; git commit
这不会为rebase打开交互式编辑会话:它只会保留从提交B
中的暂存区和树(这是git reset --soft
的一部分),直接将标签test-branch
移回到指向提交*
(这是git reset
的一部分),并像往常一样创建新提交(git commit
)。
缺点是您必须组合一个新的提交消息,但是您可以以任何多种方式从提交A
或B
中恢复提交消息。例如,您可以使用-c
或-C
标志来执行git commit
(您必须识别提交A
或B
,例如使用@{1}
或@{1}^
或@{yesterday}
或其他任何reflog说明符)。或者,在执行git reset --soft
之前,您可以使用git log
并将日志消息保存在文件中,或者采取其他措施。
(当您不仅需要压缩两个提交而是需要压缩42个提交时,此第二种方法非常有用。)
这两种方法实际上做的是同样的事情:它们添加了一个新的提交(我们称之为
AB
),使
A
和
B
变得灰色,但留下来了。我无法正确绘制:
AB <
/
...<- o <- * <
\
A <- B [ghost version of test-branch]
您的分支的幽灵版本对大多数正常使用者是不可见的,并且最终(默认情况下约30天后)会被垃圾回收。 (在此之前,它仍然位于您的存储库和引用日志中,以便您可以找到原始提交A
和B
,以防您需要它们。)
如果您已经完成了第6步怎么办? 在这种情况下,您仍然必须确定提交*
。 您可以按照我撰写本文时jsexpert建议的方法进行操作,或者您可以使用git merge-base
找到它:
$ mergebase=$(git merge-base HEAD master)
$ git rebase -i $mergebase
$ git reset --soft $mergebase; git commit
这是如何操作的。在执行
git checkout master; git fetch; git merge; git checkout test-branch
之后(步骤5和6左右),您的提交图现在看起来更像这样:
...<- o <- * <- o <
\
A <- B <
那个新的o提交,即master和origin/master指向的一个或多个提交,“挡住了路”,但是test-branch(你现在所在的分支)和master的“合并基础”是提交*:它们两个分支分叉之前最近的共享提交。
然后,我们只需将rebase或reset --soft目标设置为该提交。完成后,我们会得到一个新的AB提交,如下所示:
AB <
/
...<- o <- * <- o <
\
A <- B [ghost version of test-branch]
一旦您有了压缩的 AB 提交,您就可以像往常一样将其
git rebase
到
master
上。
请注意,另一个答案正在做完全相同的事情,只是通过计算提交来识别提交
*
。如果您知道在
test-branch
的末尾和“有趣”的提交
*
之间有两个提交,则
HEAD~2
与
$(git merge-base HEAD master)
标识相同的提交。使用
git merge-base
只是避免了计数。
"
1参考文献"是git的通用术语。在这种情况下,它们是分支名称,并且我使用单词"label"来区分它们与此提交图形形成的分支历史不同。在git中,“分支”一词用于至少这两个不同的事物,这很容易混淆。"
test-branch
中使用git rebase -i master
,然后选择压缩除最近的提交以外的所有提交。这是你要找的吗? - larsks