重新创建合并的分支



我在git的repo中有如下的分支。


_d_e_f__(branch A)
(Master)_a_b_c__/        
_g_h_i__
(branch B)

之后,从a创建新的分支C并将B合并到Cgit checkout A && git checkout -b C && git merge B


_d_e_f__(branch A)
(Master)_a_b_c__/        __________(branch C)
_g_h_i__/
(branch B)

现在,假设主分支添加了一个新的提交,我想将所有分支(a,B,C)重置到主分支的新提交。正确的做法是什么?我已经尝试了以下,一切都很好,除了当我检查图形,然而,从分支B合并到C似乎没有在rebase后集成。

git checkout A
git rebase master
git checkout B
git rebase master
git checkout C
git rebase --onto A f

从图中我可以看到,一个分离的提交(m)是为了合并B到c而创建的。

_m__C
A___/
master_____/
B

TL;DR:考虑使用石墨。我自己没有使用过Graphite,但是请阅读下面的文本,看看它是否与您的目标相匹配,然后查看链接项,可能是一种跳出框的方法。

您可以使用(1)新奇的--rebase-merges选项和(2)随后的分支名称更新来实现您的目标。这取决于你的最终目标在我写这个答案的时候,从你的问题中我并没有完全清楚这个目标。

执行此操作的命令顺序为:

git checkout branch-C
git rebase --rebase-merges master
git log --graph            # to find hash IDs below
git branch -f master <hash1>
git branch -f branch-A <hash2>
git branch -f branch-B <hash3>

,其中两个哈希id只能在git rebase --rebase-merges完成后运行git log才能发现。

这里有几件事要记住:

  • Rebase通过复制提交来工作,就像git cherry-pick一样。(--rebase-merges所做的这种重基实际上是在内部使用git cherry-pick;有些人有时会使用替代命令,这些命令可能运行得更快,但在某些情况下效果不佳。)

    每个复制的commit "做同样的事情"作为每个原始提交,并重用其原始提交的日志消息,但有一个新的,不同的哈希ID。

  • cherry-pick命令不能复制合并提交,所以--rebase-merges选项甚至不会尝试这样做。相反,在复制了作为原始合并输入的提交之后,rebase-merges代码运行一个全新的git merge命令来创建新的合并。

    因为这是一个全新的合并,所以在原始合并期间所采取的任何特殊操作都将丢失。当且仅当启用了git rerere时,以前的冲突解决方案才会保留(这将在即将发布的Git版本中出现,但在大多数现有版本和旧版本中不会出现)。您使用的任何特殊标志,如-X ours-X theirs,都将丢失。

这意味着我们开始,说:

D-----E-----F   <-- branch-A
/             
A--B--C   <-- master  M--N--O   <-- branch-C (HEAD)
             /
G-----H-----I   <-- branch-B

其中branch-A指向提交F,branch-C指向提交O,branch-B指向提交I,master指向提交C

我们在开始rebase之前检出branch-C,并使用--rebase-merges,这样Git就会生成一组列出要复制/合并的提交的指令。这组指令如下:

  1. 移动到C作为一个分离的头。
  2. 复制DEF.
  3. 保存新拷贝F'的哈希ID
  4. 返回起点C
  5. 复制GHI.
  6. 保存新拷贝I'的哈希ID
  7. 签出F'并合并I'(生成M')
  8. 复制NOP.

有一个隐含的最后指令,将名称branch-C移动到指向这里所做的最后一次提交。1如果您将--interactive添加到这个rebase中,您将看到一个文本版本的指令表,Git将允许您编辑它。如果没有,Git就使用指令表开始工作,即使没有--interactive,它也会生成和解释指令表,因为rebase可能会在中间停止。如果是这样,您可能会稍后恢复它,为此它需要保存这些指令。(rebase还会运行"已完成的工作"one_answers"下一步要做的工作",以配合待办事项指示;这里的确切机制取决于rebase代码,并且随着时间的推移而改变。

如果一切顺利,最终的结果是,之后的所有指令——包括最后和隐含的"移动分支名称";Step-have been被执行,这是:

D-----E-----F   <-- branch-A
/             
C   <-- master  M--N--O   ???
/              /
|   G-----H-----I   <-- branch-B
/
A--B

|   D'----E'----F'
 /             
C'              M'-N'-O'  <-- branch-C (HEAD)
             /
G'----H'----I'

也就是说,这个git rebase --rebase-merges已经完成了所需的所有复制,因为masterbranch-Abranch-B只需要在复制完成后指向C'F'I'提交。

不幸的是,Git本身没有任何内置的东西来处理所有这些。石墨可能。

1在写这篇文章的时候,我突然想到,如果把它作为一个明确的指令会更好。在未来的Git中,这仍然可以完成。

最新更新