如果将其中一个合并到母版,更新从功能分支中获取的姊妹子功能分支的最佳方法是什么?

时间:2018-10-26 11:31:43

标签: git merge

给出master -> AA->B1A->B2

如果将B2合并为master,那么更新B1的最佳方法是什么?

我正在尝试了解合并分支层次结构方面的最佳实践。

可接受和不可接受(即可能导致合并冲突或GitHub文件更改选项卡混乱)

什么时候应该按顺序合并回来,什么时候直接合并才有意义(无论是朝着master向后的特征分支还是朝着特征分支的master分支,还是朝着特征分支的分支之间?

2 个答案:

答案 0 :(得分:2)

我不确定我是否理解正确,但是我认为您是在问这种情况:

B1                ,-o--o--o
                 /
A             ,-o--o
             /      \         
B2          /        '-o--o
           /               \
master  --o--o--o-----------o--

在A从master分支的情况下,B1和B2从A分支的情况。

对于这样用抽象术语描述的问题,我认为没有什么可以被描述为最佳实践,它很大程度上取决于所涉及的所有分支的目的。 / p>

如果分支A代表某个功能的工作,并打算进行其他提交并在某个时候合并回master,那么我会质疑为什么B2被合并到master中而不是重新合并到master中。

如果A不能代表某个特定功能,而B1和B2可以,那么我认为B1可以合并到master中。

如果B1从A分支出来的事实是一个问题,则有可能先将其重新建立到主服务器上。

最终,答案取决于开发过程的外观以及开发过程中分支的使用方式。

答案 1 :(得分:1)

(从逻辑上讲,这应该是注释,但是我需要对其进行格式化,而我不能在注释中进行格式化。当然,它太长了。:-))

SpoonMeiser's answer中(正确和赞成),我们有这张图:

B1                ,-o--o--o
                 /
A             ,-o--o
             /      \         
B2          /        '-o--o
           /               \
master  --o--o--o-----------o--

我认为有必要指出,该图有点误导性:它使人们认为最下面一行的提交是从master可以到达的提交,而下一行是可以从B2到达的提交。 A,第三行是从B1可以到达的提交,而第一行是从C可以到达的提交。

我使用了这个奇怪的短语“ 可从到达”,而不是更明显的单词“ on ”。为什么我们称提交为 reachable 而不是只说它们在哪个分支上?

答案是,提交通常同时在许多分支上。让我们为每个提交指定一个字母名称(从A开始以避免B ,-E--F--G <-- B1 / ,-D--H <-------- A / \ / '-I--J <-- B2 / \ ...--C--K--L-----------M <-- master ),然后将分支名称移到我最喜欢的位置,在右边,就像这样:

master

Git处理这些提交的方式是从每个单独名称指向的提交开始:对于M,这是提交H,而对于分支A的是J。从此结束提交(例如分支B2的J)开始,Git 向后工作:I导致回到H,然后回到D Cmaster,依此类推。因此,分支B2包含所有这些提交。同时,分支MJ开始,该分支同时返回到Lmaster。因此B2包含L当前包含的每个提交,以及提交Kgit merge

一个人应该为git checkout使用的策略取决于一个人将来想要获得什么结果。也就是说,我们必须立即计划明天,下周或明年的工作。

git checkout的作用是提取分支名称指向的提交。例如,如果我们G分支B1,则得到提交G。存储在M中的快照进入我们的 index (到达该点时,我们将从该索引进行下一次提交)并进入我们的工作树 >(实际上我们可以在其中查看和处理文件)。如果我们进行新的提交,则将获得一个新的哈希ID-我们将在此处N ,-E--F--G--N <-- B1 (HEAD) / ,-D--H <-------- A / \ / '-I--J <-- B2 / \ ...--C--K--L-----------M <-- master 之后使用下一个字母进行绘制:

git commit

请注意,git checkout更新了当前分支(由于HEADgit checkout附加在分支名称上,Git知道了这一点),因此它现在指向刚进行的新提交。新的提交指向我们git merge编辑的提交,即当前为的提交,直到我们做出新的提交为止。

N的作用是在当前提交(现为git merge A)和我们命名的提交之间找到合并基础。如果我们说A,则名称H转换为提交H,因此Git在图中找到提交N,并在图中找到提交D,然后在该图中向后进行搜索以找到最佳的 common 提交-最佳的提交同时在 分支上。最佳翻译为“最佳”,意思是“最靠近两端”,因此这里是提交N

merge动作(要进行合并的的动词部分)实际上是通过对两个H提交Dgit diff {1}}命令:

git diff --find-renames <hash-of-D> <hash-of-N>   # what we changed
git diff --find-renames <hash-of-D> <hash-of-H>   # what they changed

Git找出我们更改了哪些文件,以及我们对它们做了什么。然后,它找出它们更改了哪些文件以及它们做了​​什么。然后,它简单地(ha)组合这两组更改。这些合并的更改将应用​​于基础D中的快照,以提供新的快照。

成功地组合了更改-至少在 Git 认为成功的情况下,Git会继续进行 merge commit ,例如{ {1}},有两个父母。第一个父级将是提交M,第二个父级将是提交N,我们选择合并。结果照常添加到H分支中,因此我们得到:

HEAD

如果我们现在要让Git合并B1和B2,Git会走这张图以找到最佳的“共同起点”。在没有提交 ,-E--F--G--N--O <-- B1 (HEAD) / ,----------' ,-D--H <-------- A / \ / '-I--J <-- B2 / \ ...--C--K--L-----------M <-- master 的情况下,该共同的起点是提交O,但是在有了D的情况下,该共同的起点是O

在所有情况下,这些“正常” Git命令只需添加到图。如果是常规提交,则每个新提交都有一个父提交;如果是合并提交,则每个新提交都有两个父提交。这些附加项重塑了图形,更改了合并,提交 future 合并将选择为其合并基础。因此,我们现在进行的合并是我们现在需要做的事情,但它们也是我们现在进行的使我们以后可能会更容易做的合并。

有些Git命令可以通过强制分支名称指向图中的另一个(旧)位置,而不是向图中添加新的提交,来删除提交。 H命令在这方面特别擅长,但是git reset也是这样做的:首先,它将一堆提交复制到“新的和改进的”提交中,然后将分支名称移动到最后一个刚刚制作的副本。通常,删除的提交实际上并不会立即消失:Git尝试给您一个月或更长时间来改变主意并将其重新带回。但是它们的确很难找到,因为Git通常查找提交的方式是从分支名称(或标签名称)开始,然后查看该名称找到的一个提交,然后使用该名称。致力于在图形中向后工作。