Git合并强制覆盖

时间:2016-11-09 22:33:26

标签: git github merge

我有一个名为demo的分支,我需要与master分支合并。我可以使用以下命令获得所需的结果:

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

我唯一担心的是,如果有任何合并问题,我想告诉git覆盖master分支中的更改而不给我合并提示。因此,demo分支中的更改基本上应自动覆盖master分支中的更改。

我环顾四周有多种选择,但我不想冒险合并。

6 个答案:

答案 0 :(得分:62)

与此答案并不真正相关,但我放弃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 noted时,-X选项会传递到合并策略,默认recursive策略和备用resolve策略都会采用-X ours或{{ 1}}(一个或另一个,但不是两个)。但是,要了解它们的作用,您需要了解Git如何找到并处理合并冲突

base 版本与当前(也称为local,HEAD或者两者)不同时,某些文件 1 内可能发生合并冲突-X theirs)版本该文件的另一个版本(也称为远程或--ours)版本。也就是说,合并确定了三个修订版(三个提交版):base,our和theirs。 "基地"版本来自我们的提交和提交之间的 merge base ,如提交图中所示(有关此内容的更多信息,请参阅其他StackOverflow帖子)。然后Git发现了两组变化:"我们做了什么"和"他们做了什么"。这些更改(通常)是逐行的,纯文本的基础。 Git对文件内容没有真正的了解;它只是比较每一行文字。

这些更改是您在--theirs输出中看到的内容,并且一如既往,它们也具有上下文。我们改变的事物可能与他们改变的事物处于不同的界限,因此变化看起来似乎不会发生碰撞,但背景也发生了变化(例如,由于我们的变化接近顶部或底部的文件,以便文件在我们的版本中用完,但在他们的版本中,他们还在顶部或底部添加了更多文本。)

如果更改发生在不同的行 - 例如,我们会在第17行将git diff更改为color并将colour更改为fred在第71行 - 然后没有冲突:Git只需要两个更改。如果更改发生在同一行,但相同的更改,Git将一次更改。只有当更改在同一行,但是是不同的更改,或干扰上下文的特殊情况时,才会发生修改/修改冲突。

barney-X ours选项告诉Git如何解决这个冲突,只选择其中一个变化:我们的,或他们的。既然你说你将-X theirs(他们的)合并到demo(我们的)并想要master的更改,你会想要demo

盲目地应用-X theirs是危险的。仅仅因为我们的变更没有逐行冲突并不意味着我们的变更实际上并没有冲突!一个经典的例子出现在具有变量声明的语言中。基本版本可能声明一个未使用的变量:

-X

在我们的版本中,我们删除未使用的变量以使编译器警告消失 - 在他们的版本中,他们稍后在某些行添加一个循环,使用int i; 作为循环计数器。如果我们将这两个更改组合在一起,则生成的代码将不再编译。 i选项在此处没有帮助,因为更改位于不同的行

如果您有自动化测试套件,最重要的是在合并后运行测试。您可以在提交后执行此操作,并在以后需要时进行修复;或者你可以在提交之前通过向-X命令添加--no-commit来完成它。我们会将所有这些内容的详细信息留给其他帖子。

1 您还可能会遇到与文件范围相关的冲突"操作,例如,我们可能修复文件中单词的拼写(以便我们进行更改),并且他们删除整个文件(以便他们删除)。无论git merge个参数如何,Git都不会自行解决这些冲突。

执行更少的合并和/或更智能的合并和/或使用rebase

我们的两个命令序列中有三个合并。第一个是将-X带入本地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:这会快进你的{{1如果可能的话,匹配更新的demo,如果没有,则完全失败(此时你可以检查两组更改,并根据需要选择真正的合并或rebase)。

同样的逻辑同样适用于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),或者将其切换为执行rebase。请注意,所有三种方法都可能失败:合并可能会因冲突而失败,与--ff-only的合并可能无法快进,并且rebase可能会因冲突而失败(rebase的工作原理是 cherry -picking 提交,它使用合并机制,因此可以获得合并冲突。)

答案 1 :(得分:9)

你可以在git merge中尝试“我们的”选项,

  

git merge branch -X our

     

此选项通过支持我们的版本,强制冲突的帅哥干净利落地自动解决。来自另一棵树的变化没有冲突                  我们这边反映了合并结果。对于二进制文件,整个内容都来自我们这边。

答案 2 :(得分:2)

这种合并方法将在master之上添加一次提交,该提交将粘贴到feature中的任何内容中,而不会抱怨冲突或其他废话。

enter image description here

触摸任何东西之前

git stash
git status # if anything shows up here, move it to your desktop

现在准备主人

git checkout master
git pull # if there is a problem in this step, it is outside the scope of this answer

打扮feature

git checkout feature
git merge --strategy=ours master

去杀人

git checkout master
git merge --no-ff feature

答案 3 :(得分:1)

我遇到了类似的问题,我需要用其他分支有效地替换所有有更改/冲突的文件。

我发现的解决方案是使用 render(){ return condition?<ThingsIWantToDisplay/>:null; //condition is a boolean }

请注意,该选项为git merge -s ours branch,而不是-s-X表示将-s用作顶级合并策略,ours会将-X选项应用于ours合并策略,这不是什么在这种情况下,我(或我们)想要。

步骤,其中recursive是您要用oldbranch覆盖的分支。

  • newbranch签出您要保留的分支
  • git checkout newbranch在旧分支中合并,但保留我们所有的文件。
  • git merge -s ours oldbranch签出您要覆盖的分支
  • git checkout oldbranch合并到新分支中,覆盖旧分支

答案 4 :(得分:0)

当我尝试使用-X theirs和其他相关命令开关时,我一直在获取合并提交。我可能没有正确理解它。一种易于理解的替代方法是删除分支,然后再次对其进行跟踪。

git branch -D <branch-name>
git branch --track <branch-name> origin/<branch-name>

这并非完全是“合并”,但这是我遇到此问题时要寻找的东西。在我的情况下,我想从远程分支中强制推送更改。

答案 5 :(得分:0)

这些命令将有助于将demo分支中的代码覆盖到master

git fetch --all

将您的demo分支拉到本地

git pull origin demo

现在将结帐到master分支。该分支将被demo分支上的代码完全更改

git checkout master

留在master分支中并运行此命令。

git reset --hard origin/demo

reset表示您将重置当前分支

--hard是一个标志,表示将在不引发任何合并冲突的情况下将其重置

origin/demo是分支,将被视为强行覆盖当前master分支的代码

以上命令的输出将显示您在origin/demodemo分支上的最后提交消息 enter image description here

最后,强行将master分支上的代码推送到您的远程仓库中。

git push --force