在Git中,将feature分支合并到master分支后会发生什么?

3

我对git merge感到困惑。

假设我从master分支中取出了feature分支,它们之间有如下分歧并进行了合并:

enter image description here

现在我想知道执行此命令后的图表会是什么样子:

git checkout master
git merge new-feature
  1. 执行以下命令后,图表会变成什么样子

    git checkout master git merge new-feature

    假设在此之后我不关闭新功能分支,并在此之后在新功能分支上再次提交一个版本。

1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
14
答案是:合并操作不会对“feature”分支产生任何影响。新的合并提交将添加到当前分支(在合并时为“master”分支)。没有现有的提交会受到影响,因为没有任何现有的提交可以被更改。 顺带一提,提交之间的箭头应该指向相反的方向。新提交指向旧提交;旧提交无法修改,所以无法“添加箭头”到旧提交。您只能创建一个新的提交,然后将其连接到一个或多个旧提交。每个指向的提交都有一个箭头。您甚至可以创建一个没有后向箭头的新提交:这是一个新的“根提交”。这是一件更高级的事情,不太常见于代码库中。 尽管ASCII艺术版本不如漂亮,但这些是相同的前后图表。
        o-o     <-- feature
       /
o--o--o--o      <-- master

[becomes:]

        o-o     <-- feature
       /   \
o--o--o--o--o   <-- master

如果您在此之后检查feature并向feature添加另一个提交,则它变为:

        o-o--o  <-- feature
       /   \
o--o--o--o--o   <-- master

编辑:让我们重新绘制上一张图片(同样的图片,我们只需要在代表提交的其中一个“o”位置上放置名称m1,以表示“合并 #1”):


        o-o--o  <-- feature
       /   \
o--o--o--o--m1  <-- master

现在假设你继续在feature上进行开发,并添加了两个新的提交:

        o-o--o--o-o    <-- feature
       /   \
o--o--o--o--m1         <-- master

然后决定再次将 feature 合并到 master 中。为了做到这一点,git 将需要创建一个新的合并提交 m2

        o-o--o--o-o    <-- feature
       /   \       \
o--o--o--o--m1------m2 <-- master

新合并的合并基础是通过查看旧合并来确定的,以便git可以确定只需要将最新的三个feature提交带入。

这就是为什么,如果您决定从feature中删除了某些内容,并在添加合并m2之前进行了“撤消”,则如果需要,您需要手动“重做”它。也就是说,假设在进行合并m1但在添加feature的三个新提交之前,您发现master已经出现问题并添加了一个提交f(“通过移除一个feature来修复”), 那么您需要手动“重做”它。

        o-o         <-- feature
       /   \
o--o--o--o--m1--f   <-- master

现在,您可以像以前一样在feature中继续工作,添加这三个提交:

        o-o------o-o-o    <-- feature
       /   \
o--o--o--o--m1--f         <-- master
现在当你执行 git merge featuremaster 时,Git 会再次找到基础版本,并知道只需将最新的三个提交中的更改合并到 f 中。
        o-o------o-o-o    <-- feature
       /   \          \
o--o--o--o--m1--f------m2 <-- master

但提交f故意禁用了一些新功能的部分。您可能需要手动修复合并(在进行提交m2之前或在提交m2后单独进行修复——如何修复由您决定),以“撤消”f中的修复,重新启用完整的功能。


无论feature是否稍后合并回master,您都可以选择是否将master合并到feature中。假设现在master中有一些特别Good的内容,应该将其带入feature中:

        o-o        <-- feature
       /   \
o--o--o--G--m1     <-- master

在这里,您只需:

git checkout feature && git merge --no-ff master

Gm1中的更改应用到feature中。当然,m1中的更改已经存在,但是git可以自己找出来,所以它只会将G中的好东西带入:

        o-o----m2  <-- feature
       /   \  /
o--o--o--G--m1     <-- master

--no-ff只需在需要显式合并提交的情况下使用,这对于突出“功能”开发线非常有用。如果省略--no-ff,那么git会观察到将m1合并到feature中会产生m1,并且只会在“快进”操作中移动分支标签:

--no-ff是 Git merge 命令的一个选项,用于禁止 Fast-forward 合并模式。Fast-forward 是一种简单的合并方式,它不会创建合并提交,而是直接将目标分支指向源分支的最新提交。当使用 --no-ff 选项时,Git 会创建一个新的合并提交,即使合并可以是快进的。

        o-o
       /   \
o--o--o--G--m1     <-- feature, master

如果你在"feature"分支上(git checkout feature)并创建了一个新的提交,那么这将导致标签master指向m1,而feature指向你的"new newest"提交:

        o-o
       /   \
o--o--o--G--m1     <-- master
              \
               o   <-- feature

我在下面放置了feature,是为了强调"top"o-o线曾经在feature上。

请注意,这张图与另一种看起来有点像蜗牛的替代绘图是相同的:

        o-o    o   <-- feature
       /   \  /
o--o--o--G--m1     <-- master

这有点暗示 o-o 可能是一项功能;但它与 这个 图形非常不同,后者包括 m2

        o-o----m2--o  <-- feature
       /   \  /
o--o--o--G--m1        <-- master

这很清楚地说明feature有一个不间断的血统,可以追溯到早期的顶部o-o。这基本上就是 "其他方向合并使用--no-ff" 的用途。

(你想要吗?那要看你自己了。像"蜗牛"一样的图表非常普遍,你会习惯它们,知道某个提交序列上的分支标签在过去的某个时间点上也经常没有什么用处。但有时候它还是很有用的,那么你就需要更像帐篷和几何形状而不是蜗牛的图形。:-))


谢谢,这就是我的错误。我以为当我合并时,功能分支也会从主分支获取提交记录,这意味着如果我要继续在功能分支上工作,那么我还需要将主分支合并到功能分支中吗? - user3147180
除非你想从master中获取新的内容,否则你不必将master合并回feature。如果你只是在feature上继续开发,并稍后再次将feature合并回master,那么“合并基础”是它最后一次合并到master的时间点。我会在图表中添加一些内容。 - torek
实际上,feature 是我的本地分支,我在这里做所有的工作,然后从主分支拉取最新的内容,首先将我的内容与主分支合并,将主分支推送到服务器,然后我还想要主分支的内容,所以我需要将主分支合并到 feature 分支。有更好的方法吗? - user3147180
非常感谢,我希望我能给你更多的投票。 - user3147180
rebase 的作用是复制提交记录,实际上是“查看那个提交记录中改变了什么,将其复制并应用到此处的另一个提交记录”。如果您对单个提交进行此操作,则称其为“cherry-pick”操作。如果您对整个提交链进行此操作,然后移动旧标签,它“看起来像”您已经移动了提交记录。实际上他们被“复制”了。如果这些提交记录是私有的,那么这样做就没问题,但如果您共享了旧副本,则情况就不太好了。有关更多信息,请参见 http://stackoverflow.com/a/18525176/1256452。 - torek
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,