繁体   English   中英

git - 在重新定位之前的壁球

[英]git - squash before rebasing

我有两个分支: mastertest-branch (从master分支出来)。 我的工作看起来如下:

  1. git checkout master
  2. git checkout -b test-branch
  3. 进行一系列更改并提交它们
  4. 进行更多更改并进行另一次提交
  5. git checkout master
  6. git pull - >其他人已经做出改变大师
  7. git checkout test-branch
  8. git rebase -i master
  9. 将交互式控制台中的s一个pick更改为s
  10. 我必须解决两个合并冲突,一个用于第一个提交,另一个用于第二个提交

我想做的是在变test-branch之前压缩test-branch上的所有提交,这样我只需要解决一次合并冲突。 这可能吗? 如果是这样,怎么样?

有可能,甚至很容易。 Git就是这样,有很多不同的方法可以做到。

从字面上做你最初的建议:

...在变基之前压缩测试分支上的所有提交

如果你在分支master上运行git merge 之前这样做是最容易的。 (我知道你没有将git merge列为命令,但你确实在第6步中运行了git merge

  1. git pull - >其他人已经做出改变大师

因为git pull只是git fetch然后是git merge 。)但它之后仍然很容易做到; 我们只需要定位正确的commit-ID。

让我们绘制您在步骤4中提交的提交图:

...<- o <- *            <-- master, origin/master
             \
               A <- B   <-- HEAD=test-branch

该图显示的是有两个标签1指向我标记为*的提交,即masterorigin/master Commit *指向提交o指向更多提交:这是分支master的历史。

您创建的分支的标签(现在开启,因此HEAD=部分)指向提交B 然后提交B指向提交A ,指向提交* 这是分支test-branch的历史:你在*时创建它,然后添加A ,然后添加B

这里有两种方法可以轻松压缩提交AB

  1. git rebase -i master

    这为您提供了一个交互式编辑会话,您可以在其中“选择”第一个提交然后“压缩”第二个提交,它将收集两个提交消息并让您以通常的方式编辑结果。 然后它进行(单个)新提交,其树是提交B的树。

  2. git reset --soft master; git commit

    打开底垫的交互式编辑会话:它只是让临时区域和树从提交B (这是--soft的一部分git reset --soft ),移动标签test-branch回点直接提交* (这是git reset --softgit reset部分),并像往常一样进行新的提交( git commit )。

    缺点是您必须编写新的提交消息,但您可以通过多种方式从提交AB恢复提交消息。 例如,您可以使用-c-C标志进行git commit (您必须标识提交AB ,例如,使用@{1}@{1}^@{yesterday}或其他一些reflog符)。 或者,在执行git reset --soft ,您可以使用git log并将日志消息保存在文件中,或者其他任何内容。

    (第二种方法闪耀时,而不是只有两次提交壁球,你有42左右。)

这两种方法都做了同样的事情:他们添加了一个新的提交(让我们称之为AB ),让AB落后并且有点灰色,我无法正确绘制:

              AB        <-- HEAD=test-branch
             /
...<- o <- *            <-- master, origin/master
             \
               A <- B   [ghost version of test-branch]

您的分支的幽灵版本对于大多数正常使用是不可见的,并且最终(默认情况下在30天左右之后)被垃圾收集掉。 (在那之前它仍然在你的存储库中,并在你的reflog中,这样你就可以找到原始提交AB ,以防万一你需要它们。)

如果你已经完成了第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

masterorigin/master指向的新o提交 - 或者它可能是整个提交链 - 是“在路上”,但test-branch的“合并基础”(你现在在哪里)和master是commit * :两个分支发散之前最近的共享提交。

然后我们简单地定位rebasereset --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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM