[英]git - squash before rebasing
我有两个分支: master
和test-branch
(从master
分支出来)。 我的工作看起来如下:
git checkout master
git checkout -b test-branch
git checkout master
git pull
- >其他人已经做出改变大师 git checkout test-branch
git rebase -i master
s
一个pick
更改为s
我想做的是在变test-branch
之前压缩test-branch
上的所有提交,这样我只需要解决一次合并冲突。 这可能吗? 如果是这样,怎么样?
有可能,甚至很容易。 Git就是这样,有很多不同的方法可以做到。
从字面上做你最初的建议:
...在变基之前压缩测试分支上的所有提交
如果你在分支master
上运行git merge
之前这样做是最容易的。 (我知道你没有将git merge
列为命令,但你确实在第6步中运行了git merge
:
git pull
- >其他人已经做出改变大师
因为git pull
只是git fetch
然后是git merge
。)但它之后仍然很容易做到; 我们只需要定位正确的commit-ID。
让我们绘制您在步骤4中提交的提交图:
...<- o <- * <-- master, origin/master
\
A <- B <-- HEAD=test-branch
该图显示的是有两个标签1指向我标记为*
的提交,即master
和origin/master
。 Commit *
指向提交o
指向更多提交:这是分支master
的历史。
您创建的分支的标签(现在开启,因此HEAD=
部分)指向提交B
然后提交B
指向提交A
,指向提交*
。 这是分支test-branch
的历史:你在*
时创建它,然后添加A
,然后添加B
这里有两种方法可以轻松压缩提交A
和B
:
git rebase -i master
这为您提供了一个交互式编辑会话,您可以在其中“选择”第一个提交然后“压缩”第二个提交,它将收集两个提交消息并让您以通常的方式编辑结果。 然后它进行(单个)新提交,其树是提交B
的树。
git reset --soft master; git commit
这不打开底垫的交互式编辑会话:它只是让临时区域和树从提交B
(这是--soft
的一部分git reset --soft
),移动标签test-branch
回点直接提交*
(这是git reset --soft
的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 <-- HEAD=test-branch
/
...<- o <- * <-- master, origin/master
\
A <- B [ghost version of test-branch]
您的分支的幽灵版本对于大多数正常使用是不可见的,并且最终(默认情况下在30天左右之后)被垃圾收集掉。 (在那之前它仍然在你的存储库中,并在你的reflog中,这样你就可以找到原始提交A
和B
,以防万一你需要它们。)
如果你已经完成了第6步怎么办? 在这种情况下,您仍必须识别commit *
。 你可以像我写这篇文章时那样按照jsexpert的建议去做 ,或者你可以用git merge-base
找到它:
$ mergebase=$(git merge-base HEAD master)
# then pick just ONE of the next two
$ git rebase -i $mergebase
$ git reset --soft $mergebase; git commit
这是如何工作的。 git checkout master; git fetch; git merge; git checkout test-branch
git checkout master; git fetch; git merge; git checkout test-branch
git checkout master; git fetch; git merge; git checkout test-branch
(步骤5和6,或多或少),你的提交图现在看起来更像是这样的:
...<- o <- * <- o <-- master, origin/master
\
A <- B <-- HEAD=test-branch
master
和origin/master
指向的新o
提交 - 或者它可能是整个提交链 - 是“在路上”,但test-branch
的“合并基础”(你现在在哪里)和master
是commit *
:两个分支发散之前最近的共享提交。
然后我们简单地定位rebase
或reset --soft
在该提交。 当我们完成并有一个新的AB
提交时,它看起来像这样:
AB <-- HEAD=test-branch
/
...<- o <- * <- o <-- master, origin/master
\
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中的“branch”一词用来指代至少这两个不同的东西,它会让人感到困惑。
当然有可能,yoiu只需要键入: git rebase -i HEAD~<# of commits to squash>
#snits git rebase -i HEAD~<# of commits to squash>
-i用于交互式rebase。 一旦你这样做,你将看到vi,其中包含每次提交下一步的说明。
关于它的非常详细的帖子可以在这里找到重写历史 :
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.