有一个“他们的”版本的“混帐 – 我们的”?
当使用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 gitster
( gitster
)的 提交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
发出一个合并请求,使其成为新的主节点,或者将其保留为分支。