有一个“他们的”版本的“混帐 – 我们的”?

当使用git merge将主题分支“B”合并到“A”时,我遇到了一些冲突。 我知道所有的冲突都可以用“B”中的版本来解决。

我知道git merge -s ours 。 但是我想要的就是像git merge -s theirs东西。

为什么不存在? 在与现有的git命令冲突之后,我怎么能达到相同的结果? ( git checkout每个未被合并的文件从B)

更新:只是丢弃分支A(树的合并提交点到B版本)任何东西的“解决scheme”是不是我所期待的。

-X选项添加到theirs 。 例如:

 git checkout branchA git merge -X theirs branchB 

一切都将以所需的方式合并。

我见过的唯一的问题是如果从branchB删除文件。 如果除git之外的东西去除,它们就会显示为冲突。

修复很简单。 只要用删除的文件的名字来运行git rm

 git rm {DELETED-FILE-NAME} 

之后, -X theirs应该按预期工作。

当然,使用git rm命令进行实际的删除将首先防止冲突的发生。


注意 :还有一个更长的表单选项。 太使用它,replace:

 -X theirs 

有:

 --strategy-option=theirs 

将分支机构B合并到我们的检出分支机构A的一种可能且经过testing的解决scheme:

 # in case branchA is not our current branch git checkout branchA # make merge commit but without conflicts!! # the contents of 'ours' will be discarded later git merge -s ours branchB # make temporary branch to merged commit git branch branchTEMP # get contents of working tree and index to the one of branchB git reset --hard branchB # reset to our merged commit but # keep contents of working tree and index git reset --soft branchTEMP # change the contents of the merged commit # with the contents of branchB git commit --amend # get rid off our temporary branch git branch -D branchTEMP # verify that the merge commit contains only contents of branchB git diff HEAD branchB 

要自动化,可以使用branchA和branchB作为参数将其包装到脚本中。

这个解决scheme保留了合并提交的第一个和第二个父代,就像你期望的git merge -s theirs branchB

老版本的git允许你使用“他们的”合并策略:

 git pull --strategy=theirs remote_branch 

但是这个消息已经被删除了,正如Junio Hamano (Git的维护者)在这个消息中所解释的那样。 正如在链接中指出的,相反,你会这样做:

 git fetch origin git reset --hard origin 

但要小心,这是不同于实际的合并。 您的解决scheme可能是您真正想要的选项。

从此以后,我使用了Paul Pladijs的答案。 我发现,你可以做一个“正常”合并,发生冲突,所以你这样做

 git checkout --theirs <file> 

通过使用其他分支的修订来解决冲突。 如果您为每个文件执行此操作,则具有与您所期望的相同的行为

 git merge <branch> -s theirs 

无论如何,这个努力远不止于合并策略! (这是用git 1.8.0testing的)

目前尚不完全清楚你想要的结果是什么,所以在答案和评论中对“正确”的做法有一些困惑。 我尝试给出一个概述,并看到以下三个选项:

尝试合并并使用B进行冲突

不是 “他们的git merge -s ours版本”,而是他们的“ git merge -X ours版本”(这是git merge -s recursive -X ours简称 – git merge -s recursive -X ours ):

 git checkout branchA # also uses -s recursive implicitly git merge -X theirs branchB 

这就是例如Alan W. Smith的答案 。

仅使用来自B的内容

这会为两个分支创build合并提交,但会丢弃branchA所有更改,并只保留branchB的内容。

 # Get the content you want to keep. # If you want to keep branchB at the current commit, you can add --detached, # else it will be advanced to the merge commit in the next step. git checkout branchB # Do the merge an keep current (our) content from branchB we just checked out. git merge -s ours branchA # Set branchA to current commit and check it out. git checkout -B branchA 

请注意,现在合并提交第一个父节点是来自branchB ,而第二个来自branchA 。 这就是Gandalf458的答案 。

仅使用来自B的内容并保持正确的父母顺序

这是真正的“他们的git merge -s ours版本 – git merge -s ours ”。 它与之前的选项(即仅来自branchB )具有相同的内容,但父母的顺序是正确的,即第一个父代来自branchA ,第二个来自branchB

 git checkout branchA # Do a merge commit. The content of this commit does not matter, # so use a strategy that never fails. # Note: This advances branchA. git merge -s ours branchB # Change working tree and index to desired content. # --detach ensures branchB will not move when doing the reset in the next step. git checkout --detach branchB # Move HEAD to branchA without changing contents of working tree and index. git reset --soft branchA # 'attach' HEAD to branchA. # This ensures branchA will move when doing 'commit --amend'. git checkout branchA # Change content of merge commit to current index (ie content of branchB). git commit --amend -C HEAD 

这就是Paul Pladijs的答案 (不需要临时分支)。

我解决了我的问题使用

 git checkout -m old git checkout -b new B git merge -s ours old 

如果你在分支A上做:

 git merge -s recursive -X theirs B 

在git 1.7.8上testing

当使用git merge合并“A”中的主题分支“B”时,我遇到了一些冲突。 我知道所有的冲突都可以用“B”中的版本来解决。

我知道git合并 – 我们的。 但是我想要的东西就像git merge> – 是他们的。

我假设你创build了一个关于master的分支,现在想要合并回master,覆盖master中的任何旧的东西。 当我遇到这个post的时候,这正是我想要做的。

做你想做的事情,除了把一个分支合并到另一个分支。 我刚刚做到了,而且效果很好。

 git checkout Branch git merge master -s ours 

然后,结帐主,并合并你的分支(现在会顺利):

 git checkout master git merge Branch 

要真正正确地做一个合并, 需要你正在合并的分支的input,你可以做

git merge --strategy=ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

在我所知的任何情况下都不会有任何冲突,您不必创build额外的分支,就像正常的合并提交一样。

但是,这对子模块来说并不好用。

查看Junio Hamano被广泛引用的答案 :如果您要放弃承诺的内容,就放弃提交,或者至less将其放在主要历史logging之外。 为什么在将来阅读提交信息时,为什么要打扰提交的消息呢?

但有时候有行政要求,或者其他原因。 对于那些你确实需要logging没有任何贡献的提交的情况,你需要:

(编辑:哇,我之前是否设法弄错了,这个是有效的。)

 git update-ref HEAD $( git commit-tree -m 'completely superseding with branchB content' \ -p HEAD -p branchB branchB: ) git reset --hard 

这个使用了git plumbing命令的读取树,但是使得整个工作stream程更短。

 git checkout <base-branch> git merge --no-commit -s ours <their-branch> git read-tree -u --reset <their-branch> git commit # Check your work! git diff <their-branch> 

这将合并您的newBranch在现有baseBranch

 git checkout <baseBranch> // this will checkout baseBranch git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch) git checkout newBranch -- . //this will replace all conflicted files in baseBranch 

UPDATE

第二个答案回答了原来的问题,但并不能反映议员问题的更新意图。


你正在寻找不是相反的git merge -s ours命令你正在寻找相反的git merge -s recursive -X ours命令,这是git merge -s recursive -X theirs


原始答复

给原来的分支

 * 0123456 (HEAD->A, origin/A) | * 1234556 (origin/B, B) |/ * ??????? (common root) 

要将分支B合并到A中而忽略分支A的状态,则首先进行常规合并

 git merge -s ours B (this is the opposite of what we want) 

这导致

 * 2345678 (HEAD->A) Merge branch 'B' into A (all wrong) |\ * | 0123456 (origin/A) | * 1234567 (origin/B, B) |/ * ??????? (common root) 

因为提交ID将会改变(这是错误的),所以现在我们可以在事实之后将ours策略改变成theirs策略

不要忘记写下合并的提交ID,因为在下一次硬重置之后它将不可用。 (如果你忘记没有损坏将会完成,但你将不得不做一个硬重置回A并重新开始)。

 git reset --hard B (this is what we want the merge to look like (the merge can now only be referenced by the commit id `2345678`)) git reset --soft 2345678 (without changing any files go back to the merge) git commit --amend (branch B is now the final version of the merge) 

现在我们有

 * 3456789 (HEAD->A) Merge branch 'B' into A (correctly ignores changes from 0123456) |\ * | 0123456 (origin/A) | * 1234567 (origin/B, B) |/ * ??????? (common root) $ diff HEAD B [... no changes ...] git push 

DONE

当同事将我的变更A到他的独立分支B而不合并时,我需要这样做,这使我能够在我的分支上接受他的修改。

为什么不存在?

虽然我在“ git命令让一个分支像另一个分支”那样,如何模拟git merge -s theirs ,请注意,Git 2.15(2017年第四季度)现在更清晰了:

用于合并的' -X<option> '的文档被误导性地写成表示存在“ – -s theirs ”,事实并非如此。

参见Junio C gitstergitster )的 提交c25d98b (2017年9月25日) 。
(由Junio C gitster合并- gitster – in commit 4da3e23 ,2017年9月28日)

合并策略:避免暗示“ -s theirs ”存在

-Xours合并选项的描述有一个括号内的注释,告诉读者它与-s ours是非常不同的,这是正确的,但是他们随后的-Xtheirs的描述不小心地说:“这与ours的相反”一个错误的印象是,读者也需要警告,这与-s theirs实际上根本不存在是完全不同的。

-Xtheirs是他们应用recursion策略的策略select 。 这意味着recursion策略仍然会合并任何可能的,并且只会在冲突情况theirs退到“ theirs ”逻辑。

针对theirs合并策略的针对性或不针对性的争论最近在2017年9月的线索中被带回。
它承认较旧的(2008)线程

总之,前面的讨论可以总结为“我们不希望',因为它鼓励错误的工作stream程。

它提到了别名:

 mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' - 

雅罗斯拉夫·哈尔琴科(Yaroslav Halchenko)试图再次提倡这一策略, 但是Junio C. Hamano补充道 :

我们的和他们的不对称的原因是因为你是你而不是他们—我们的历史和历史的控制和所有权是不对称的。

一旦你决定他们的历史是主线,你宁愿要把你的发展路线作为一个支线,并在这个方向上合并,即最终的合并的第一个父母是对他们的历史提交,第二个家长是你历史上最后一个糟糕的人。 所以你最终会使用“ checkout their-history && merge -s ours your-history ”,以保持第一个父母的感性。

而在这一点上,使用“ -s ours ”不再是解决缺乏“ -s theirs ”的方法。
它是理想语义学的一个适当部分,也就是说,从存活的规范的历史线的angular度来看,你想要保留它所做的,使其他历史线所做的事情无效

我想你真正想要的是:

 git checkout -B mergeBranch branchB git merge -s ours branchA git checkout branchA git merge mergeBranch git branch -D mergeBranch 

这似乎笨拙,但它应该工作。 唯一觉得我真的不喜欢这个解决scheme的是,git的历史将会让人困惑……但是至less历史将被完全保留下来,而且你不需要为删除的文件做一些特殊的事情。

我最近需要为共享一个共同的历史的两个独立的存储库做到这一点。 我开始:

  • Org/repository1 master
  • Org/repository2 master

我希望将repository1 master所有更改应用到repository1 master ,并接受repository2将做的所有更改。 用git的话来说,这应该是一个叫做-s theirs的策略,但它不存在。 要小心,因为-X theirs的名字就像是你想要的,但它一样(甚至在手册页中也这么说)。

我解决这个问题的方法是去repository2并创build一个新的分支repo1-merge 。 在那个分支中,我运行git pull git@gitlab.com:Org/repository1 -s ours ,它合并很好,没有问题。 然后我把它推到遥控器上。

然后我回到repository1并创build一个新的分支repo2-merge 。 在那个分支中,我运行git pull git@gitlab.com:Org/repository2 repo1-merge将会完成问题。

最后,您需要在repository1发出一个合并请求,使其成为新的主节点,或者将其保留为分支。