Git合并强制覆盖

Ope*_*ack 71 git merge github

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

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master
Run Code Online (Sandbox Code Playgroud)

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

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

tor*_*rek 77

不是真的与此相关的答案,但我会沟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
Run Code Online (Sandbox Code Playgroud)

控制最棘手的合并

这里最有趣的部分是git merge -X theirs.正如root545所指出的那样,-X选项被传递给合并策略,默认recursive策略和替代resolve策略都采用-X ours-X theirs(一个或另一个,但不是两个).但是,要了解它们的作用,您需要知道Git如何找到并处理,合并冲突.

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

这些更改是您在git diff输出中看到的,并且一如既往,它们也具有上下文.我们改变的东西可能与他们改变的东西不同,所以变化看起来好像不会碰撞,但是上下文也发生了变化(例如,由于我们的变化接近文件的顶部或底部,所以文件在我们的版本中耗尽,但在他们的版本中,他们还在顶部或底部添加了更多文本).

如果更改发生在不同的行上 - 例如,我们更改colorcolour第17行并且它们更改fredbarney第71行 - 那么就没有冲突:Git只需要进行两次更改.如果更改发生在同一行,但是相同的更改,Git将获取更改的一个副本.仅当更改位于同一行,但是更改不同或干扰上下文的特殊情况时,才会出现修改/修改冲突.

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

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

int i;
Run Code Online (Sandbox Code Playgroud)

在我们的版本中,我们删除了未使用的变量以使编译器警告消失 - 在他们的版本中,他们稍后使用i循环计数器添加一些循环.如果我们将这两个更改组合在一起,则生成的代码将不再编译.-X由于更改位于不同的行,因此该选项无效.

如果您有自动化测试套件,最重要的是在合并后运行测试.您可以在提交后执行此操作,并在以后需要时进行修复; 或者你可以做到这一点之前提交,通过添加--no-commitgit merge命令.我们会将所有这些的详细信息留给其他帖子.


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


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

我们的两个命令序列中有三个合并.第一个是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,并且如果没有,则完全失败(此时您可以检查两组更改,并根据需要选择真正的合并或rebase).

这个逻辑同样适用于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
Run Code Online (Sandbox Code Playgroud)

如果你正在做你自己的demo分支提交,这是没有帮助的; 你可以保留现有的合并(但可能--ff-only根据你想要的行为添加),或者将其切换为执行rebase.请注意,所有三种方法都可能失败:合并可能会因冲突而失败,合并--ff-only可能无法快进,并且rebase可能会因冲突而失败(rebase的工作原理是,实际上,使用合并的挑选提交机器,因此可以得到合并冲突).


Wil*_*ken 35

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

在此处输入图片说明

在你触摸任何东西之前

git stash
git status # if anything shows up here, move it to your desktop
Run Code Online (Sandbox Code Playgroud)

现在准备大师

git checkout master
git pull # if there is a problem in this step, it is outside the scope of this answer
Run Code Online (Sandbox Code Playgroud)

整装feature待发

git checkout feature
git merge --strategy=ours master
Run Code Online (Sandbox Code Playgroud)

去杀戮

git checkout master
git merge --no-ff feature
Run Code Online (Sandbox Code Playgroud)

  • git 推动完成 (3认同)

Nia*_*ack 10

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

我发现的解决方案是使用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 签出您要覆盖的分支
  • get merge newbranch 合并到新分支中,覆盖旧分支

  • 如果有人碰巧遇到提示“请输入提交消息来解释为什么需要进行此合并”的情况:输入消息,然后按键盘上的 ESC 键,键入 :wq 并按 ENTER 退出提示。 (2认同)

man*_*nuj 9

您可以在git merge中尝试"我们的"选项,

git merge branch -X our

此选项通过支持我们的版本强制冲突的帅哥干净地自动解决.来自与我们方不冲突的其他树的更改将反映到合并结果中.对于二进制文件,整个内容都来自我们这边.

  • 这将是倒退,因为OP表示即使他要合并到“ master”中,他也希望“ demo”版本是首选。也有“ -X他们的”,但是不清楚这是OP真正想要的。 (2认同)

Rah*_*and 8

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

git fetch --all
Run Code Online (Sandbox Code Playgroud)

demo在本地拉你的分支

git pull origin demo
Run Code Online (Sandbox Code Playgroud)

现在结帐到master分支。这个分支将随着demo分支上的代码完全改变

git checkout master
Run Code Online (Sandbox Code Playgroud)

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

git reset --hard origin/demo
Run Code Online (Sandbox Code Playgroud)

reset 意味着您将重置当前分支

--hard 是一个标志,意味着它将被重置而不会引发任何合并冲突

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

上述命令的输出将显示您在origin/demodemo分支 上的最后一次提交消息在此处输入图片说明

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

git push --force
Run Code Online (Sandbox Code Playgroud)


Mat*_*att 6

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

git branch -D <branch-name>
git branch --track <branch-name> origin/<branch-name>
Run Code Online (Sandbox Code Playgroud)

这不完全是“合并”,但这正是我遇到这个问题时所寻找的。就我而言,我想从强制推送的远程分支中提取更改。