我对git merge感到困惑。
假设我从master
分支中取出了feature
分支,它们之间有如下分歧并进行了合并:
现在我想知道执行此命令后的图表会是什么样子:
git checkout master
git merge new-feature
执行以下命令后,图表会变成什么样子
git checkout master
git merge new-feature
假设在此之后我不关闭新功能分支,并在此之后在新功能分支上再次提交一个版本。
我对git merge感到困惑。
假设我从master
分支中取出了feature
分支,它们之间有如下分歧并进行了合并:
现在我想知道执行此命令后的图表会是什么样子:
git checkout master
git merge new-feature
执行以下命令后,图表会变成什么样子
git checkout master
git merge new-feature
假设在此之后我不关闭新功能分支,并在此之后在新功能分支上再次提交一个版本。
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 feature
到 master
时,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
中有一些特别G
ood的内容,应该将其带入feature
中:
o-o <-- feature
/ \
o--o--o--G--m1 <-- master
在这里,您只需:
git checkout feature && git merge --no-ff master
将G
和m1
中的更改应用到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
" 的用途。
(你想要吗?那要看你自己了。像"蜗牛"一样的图表非常普遍,你会习惯它们,知道某个提交序列上的分支标签在过去的某个时间点上也经常没有什么用处。但有时候它还是很有用的,那么你就需要更像帐篷和几何形状而不是蜗牛的图形。:-))
master
中获取新的内容,否则你不必将master
合并回feature
。如果你只是在feature
上继续开发,并稍后再次将feature
合并回master
,那么“合并基础”是它最后一次合并到master
的时间点。我会在图表中添加一些内容。 - torekfeature
是我的本地分支,我在这里做所有的工作,然后从主分支拉取最新的内容,首先将我的内容与主分支合并,将主分支推送到服务器,然后我还想要主分支的内容,所以我需要将主分支合并到feature
分支。有更好的方法吗? - user3147180rebase
的作用是复制提交记录,实际上是“查看那个提交记录中改变了什么,将其复制并应用到此处的另一个提交记录”。如果您对单个提交进行此操作,则称其为“cherry-pick”操作。如果您对整个提交链进行此操作,然后移动旧标签,它“看起来像”您已经移动了提交记录。实际上他们被“复制”了。如果这些提交记录是私有的,那么这样做就没问题,但如果您共享了旧副本,则情况就不太好了。有关更多信息,请参见 http://stackoverflow.com/a/18525176/1256452。 - torek