不是真的与此相关的答案,但我会沟git pull
,只需运行它git fetch
之后git merge
。您正在执行三个合并,这将使您的Git运行三个获取操作,而只需要一次获取。因此:
git fetch origin # update all our origin/* remote-tracking branches
git checkout demo # if needed -- your example assumes you're on it
git merge origin/demo # if needed -- see below
git checkout master
git merge origin/master
git merge -X theirs demo # but see below
git push origin master # again, see below
控制最棘手的合并
这里最有趣的部分是git merge -X theirs
。正如root545指出的那样,这些-X
选项将传递到合并策略,默认recursive
策略和替代resolve
策略都采用-X ours
或-X theirs
(一个或另一个,但不能同时使用)。但是,要了解它们的作用,您需要知道Git如何发现和对待并合并冲突。
当基本版本不同于同一文件的当前版本(也称为本地版本,HEAD 版本)和其他版本(也称为远程版本)时,某些文件1内可能发生合并冲突。也就是说,合并确定了三个修订版(三个提交):基本版本,我们的版本和他们的版本。“基础”版本来自提交和提交之间的合并基础,如提交图中所示(有关更多信息,请参见其他StackOverflow发布)。然后,Git找到了两组更改:“我们做了什么”和“他们做了什么”。这些更改(通常)逐行(纯文本)--ours
--theirs
基础。Git对文件内容没有真正的了解;它只是比较文本的每一行。
这些更改是您在git diff
输出中看到的,并且一如既往,它们也具有上下文。我们更改的内容可能与更改的内容不在同一行,因此更改似乎不会发生冲突,但是上下文也已更改(例如,由于更改接近文件的顶部或底部,因此该文件在我们的版本中用尽,但在他们的版本中,他们还在顶部或底部添加了更多文本)。
如果更改发生在不同的行上(例如,我们更改color
为colour
第17行,而更改fred
为barney
第71行),则不存在冲突:Git只需接受这两个更改。如果更改发生在同一行,但是是相同的更改,则Git会获取该更改的一个副本。仅当更改是在同一行上,但是是不同的更改,或者是干扰上下文的特殊情况时,您才会获得修改/修改冲突。
在-X ours
和-X theirs
选项告诉Git是如何解决这个矛盾,采摘只是其中一个变化:我们的,还是他们。既然您说过您正在将demo
(他们的)合并到master
(我们的)并希望从中进行更改demo
,那么您就想要-X theirs
。
-X
但是,盲目使用是危险的。仅仅因为我们的更改没有逐行冲突并不意味着我们的更改实际上没有冲突!一个经典的例子出现在带有变量声明的语言中。基本版本可能会声明一个未使用的变量:
int i;
在我们的版本中,我们删除了未使用的变量以使编译器警告消失—在它们的版本中,它们在以后的几行中添加了一个循环,i
用作循环计数器。如果我们将这两个更改组合在一起,则生成的代码将不再编译。-X
由于更改位于不同的行,因此该选项无济于事。
如果您具有自动化测试套件,那么最重要的事情是在合并后运行测试。您可以在提交后执行此操作,然后在需要时进行修复。或者您可以在提交之前通过添加--no-commit
到git merge
命令中来完成此操作。我们会将所有这些详细信息留给其他帖子。
1您也可能会在“文件范围”操作方面发生冲突,例如,也许我们修复了文件中某个单词的拼写(以便我们进行更改),然后删除了整个文件(因此他们拥有了一个删除)。无论有何-X
论点,Git都不会自行解决这些冲突。
进行更少的合并和/或更明智的合并和/或使用变基
我们的两个命令序列都有三个合并。首先是origin/demo
引入本地demo
(git pull
如果您的Git很旧,您将使用该版本,origin/demo
但更新失败,但会产生相同的最终结果)。二是origin/master
带入master
。
我不清楚谁正在更新demo
和/或master
。如果您在自己的demo
分支上编写自己的代码,而其他人正在编写代码并将其推送到上的demo
分支上origin
,则此第一步合并可能会发生冲突,或产生实际的合并。通常,使用rebase而不是合并来结合工作是更好的选择(不可否认,这是一种品味和见解的问题)。如果是这样,您可能要git rebase
改用。在另一方面,如果你从来没有做任何自己提交的对demo
,你甚至都不需要一个demo
分支。另外,如果您想自动执行很多操作,但是能够仔细检查何时有您和其他人进行的提交,则可以使用git merge --ff-only origin/demo
:如果可能的话,这将使您快速demo
匹配更新的内容,origin/demo
如果没有,则完全失败(此时您可以检查两组更改,并根据需要选择真正的合并或变基)。
这个逻辑同样适用于master
,即使你正在做的合并上 master
,所以你绝对需要master
。但是,如果合并不能作为快进的非合并完成,则您甚至更可能希望合并失败,因此也应该这样做git merge --ff-only origin/master
。
假设您从不对自己进行提交demo
。在这种情况下,我们可以demo
完全放弃该名称:
git fetch origin # update origin/*
git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"
git merge -X theirs origin/demo || die "complex merge conflict"
git push origin master
如果您正在执行自己的demo
分支提交,这将无济于事。您也可以保留现有合并(但可以--ff-only
根据所需的行为添加),也可以将其切换为进行基准调整。请注意,这三种方法都可能失败:合并可能会因冲突而失败,与合并--ff-only
可能无法快速前进,而重新基准化可能会因冲突而失败(本质上,重新合并是通过使用合并进行的精心挑选的提交来进行的。机械,因此可能会发生合并冲突)。
git push -f origin master