Git 重新定基是否是修复错误樱桃采摘的唯一方法?
分支#1包含错误修复C1。分行2首先樱桃采摘对C1进行了修复,然后分行2的所有者意识到C1中所做的工作实际上是错误的,因此他实施了正确的修复C2 在C2中,他基本上删除了C1中的更改,并替换为正确的更改。当分行1所有者想要“获取”修复时,合并将无法工作。因为使用merge时,结果C3将包含C1和C2中引入的正确修复,即C1将由merge保留Git 重新定基是否是修复错误樱桃采摘的唯一方法?,git,git-merge,git-rebase,git-cherry-pick,Git,Git Merge,Git Rebase,Git Cherry Pick,分支#1包含错误修复C1。分行2首先樱桃采摘对C1进行了修复,然后分行2的所有者意识到C1中所做的工作实际上是错误的,因此他实施了正确的修复C2 在C2中,他基本上删除了C1中的更改,并替换为正确的更改。当分行1所有者想要“获取”修复时,合并将无法工作。因为使用merge时,结果C3将包含C1和C2中引入的正确修复,即C1将由merge保留 Because the branch #2 now does NOT contain C1 codes at all so merge won't work
Because the branch #2 now does NOT contain C1 codes at all so merge won't work.
base -- C1'-- C2'(remove C1' change) -- C2''(add the correct fix) <--branch #2
/---- C1---------------C3 (merge won't do b/c C1 will be kept) <-- branch #1
base /
\---- C1' ---- C2----/ <--branch #2
因为分支#2现在根本不包含C1代码,所以合并无法工作。
基本--C1'--C2'(删除C1'更改)--C2''(添加正确的修复)
所以问题是,如果我知道有人会选择我的提交,我最好重新设置他的分支的基础,而不是合并
是的,因为正如我前面所说的,一个cherry pick在分支之间复制了一个commit。由于重基跳过重复提交,这是一个很好的解决方法。
有关具体说明,请参见“”
有没有其他方法可以避免(或解决)我在这里提到的问题
如果您打算最终合并两个分支,那么在这两个分支之间就不应该有樱桃采摘。仅合并或重设基础
只有在分支不应该合并的情况下,Cherry选择错误修复是个好主意
所以问题是,如果我知道有人会选择我的提交,我最好重新设置他的分支的基础,而不是合并
是的,因为正如我前面所说的,一个cherry pick在分支之间复制了一个commit。由于重基跳过重复提交,这是一个很好的解决方法。
有关具体说明,请参见“”
有没有其他方法可以避免(或解决)我在这里提到的问题
如果您打算最终合并两个分支,那么在这两个分支之间就不应该有樱桃采摘。仅合并或重设基础
只有在分支不应该合并的情况下,Cherry选择错误修复是个好主意。您基本上是正确的。然而,重新设定基准并不是解决问题的万灵丹
让我们画一个稍微复杂一点的情况。我们将从一个类似的提交图开始:
...--o--o
这里的最后一个o
节点是某个分支的tip commit,而之前的一些commito
也不是很明显。我们不会为分支标签费心,因为它们只是为了帮助人类,我们关注的是Git做了什么,而不是人类做了什么。:-)
出现了一个人,他进行了一次新的提交,您的提交C1
(不过我将其称为C
),其中有一个bug:
C
/
...--o--o
与此同时,在这份回购协议中,或者在它的其他复制品中,出现了一个不同的人,他做出了一个不相关的承诺F
:
C
/
...--o--*
\
F
提交C
和F
可能位于不同的(命名的)分支上,但重要的是它们有一个公共基*
(这过去只是标记为o
,但现在我们需要记住,它是公共基,尽管从图纸上看很明显)
在您的特定场景中,第二个用户通过樱桃采摘C
生成了F
。假设在我们的例子中,第二个用户相当独立地制作了F
。现在,第二个用户决定现在是挑选C
的时候了,所以他们得到了它的一个副本,但它并没有完全应用,所以他们会稍微更改它,手动编辑它,使其应用。现在他们有:
C
/
...--o--*
\
F--G
请再次注意,commitG
主要是C
的一个副本,但并非完全如此,正如我们所指出的,它将被视为有缺陷的
因此,您的第一个人将C
还原为实际上将其从其分支中移除,然后添加D
(更正的修复):
您的第二个人继续添加更多提交:
C--R--D <-- branch1
/
...--o--*
\
F--G--H--I <-- branch2
因此,虽然git merge
肯定会失败,git rebase
有时也会失败(特别是当必须修改提交以适应时)。在这种情况下,发生这种情况是因为F
和C
之间存在冲突,但是有很多方法可以解决这个问题
有没有其他方法可以避免(或解决)我在这里提到的问题
理想的情况是,无论谁在branch2
上工作,都不必一开始就选择C
,而只需要在C
上重新设置基址,然后在需要时(或者直接在D
上重新设置基址),或者在所述重新设置基址后合并。让我们看看如果第二个人在branch2
工作,将他的F
commit重设为C
,而不是樱桃采摘,那么这个图会是什么样子。让我们在重设基础之前绘制:
C <-- branch1
/
...--o--*
\
F <-- branch2
现在,让我们将F
复制到F'
顶部C
并移动分支标签:
...--o--*---C <-- branch1
\ \
\ F' <-- branch2
\
F [abandoned]
如果我们现在使用git merge
将commitI
合并到commitD
上,我们不会通过G
重新引入错误的commitC
,因为现在没有G
当然,如果有多人使用branch2
——如果发布了旧的F
commit,那么每次我们重新设置基址时,这意味着他们都必须切换到使用新的副本
测试
有没有其他方法可以避免(或解决)我在这里提到的问题
理想情况下,当有人发现bug时,在编写commitC
之前,他们会编写一个测试用例。测试用例显示commitC
是必需的,commitC
修复了这个bug,这就是commitC
首先被提交的原因
当发现C
有故障时,应该改进它的测试用例,或者编写一个额外的测试用例,以证明提交C
并不完全正确。这也是为什么revertR
进入,以及后续更好的修复D
的原因。(也许D
本质上是R
的挤压和替换修复?
C--R--D <-- branch1
/ \
...--o--* F'-G'-H'-I' <-- branch2
\
F--G--H--I [abandoned]
C <-- branch1
/
...--o--*
\
F <-- branch2
...--o--*---C <-- branch1
\
F <-- branch2
...--o--*---C <-- branch1
\ \
\ F' <-- branch2
\
F [abandoned]
...--o--o---C--R--D <-- branch1
\
F'-H--I <-- branch2