是否有“他们的”版本的“git merge -s ours”?

时间:2008-10-06 11:16:43

标签: git git-merge

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

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

为什么不存在?在与现有git命令冲突合并后,如何获得相同的结果? (git checkout来自B的所有未合并文件

更新:从分支A(合并提交点到树的B版本)丢弃任何东西的“解决方案”不是我想要的。

18 个答案:

答案 0 :(得分:902)

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

git checkout branchA
git merge -X theirs branchB

所有东西都会以所需的方式合并。

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

修复很简单。只需使用已删除的文件的名称运行git rm

git rm {DELETED-FILE-NAME}

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

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


注意:还存在更长的表单选项。要使用它,请替换:

-X theirs

使用:

--strategy-option=theirs

答案 1 :(得分:194)

一种可行且经过测试的解决方案,用于将branchB合并到我们的签出分支A:

# 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作为参数将其包装到脚本中。

此解决方案保留合并提交的第一个和第二个父级,就像您对git merge -s theirs branchB的期望一样。

答案 2 :(得分:83)

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

git pull --strategy=theirs remote_branch

但是这已被删除,正如Junio Hamano(Git维护者)在此消息中所解释的那样。如链接中所述,您可以这样做:

git fetch origin
git reset --hard origin

请注意,这与实际合并不同。您的解决方案可能是您真正想要的选择。

答案 3 :(得分:60)

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

git checkout --theirs <file>

通过使用其他分支的修订来解决冲突。如果对每个文件执行此操作,则会产生与

相同的行为
git merge <branch> -s theirs

无论如何,努力比合并策略更多! (这是使用git版本1.8.0测试的)

答案 4 :(得分:53)

目前还不完全清楚您期望的结果是什么,因此在答案及其评论中采用“正确”方式存在一些混淆。我尝试概述并看到以下三个选项:

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

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

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

这就是例如Alan W. Smith's answer确实如此。

仅使用B中的内容

这会为两个分支创建合并提交,但会丢弃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's answer确实如此。

仅使用B中的内容并保持正确的父订单

这是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 (i.e. content of branchB).
git commit --amend -C HEAD

这是Paul Pladijs's answer的作用(不需要临时分支)。

答案 5 :(得分:20)

我用

解决了我的问题
git checkout -m old
git checkout -b new B
git merge -s ours old

答案 6 :(得分:14)

如果你在分支A上做:

git merge -s recursive -X theirs B

在git 1.7.8版本上测试

答案 7 :(得分:8)

  

使用git merge在“A”中合并主题分支“B”时,会出现一些冲突。我&gt;知道可以使用“B”中的版本解决所有冲突。

     

我知道我们的git merge -s。但我想要的是像git merge&gt; -s他们的东西。

我假设你创建了一个master的分支,现在想要合并回master,覆盖master中的任何旧东西。这正是我在遇到这篇文章时想要做的事情。

完全按照你想做的去做,除了先将一个分支合并到另一个分支。我刚刚这样做了,效果很好。

git checkout Branch
git merge master -s ours

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

git checkout master
git merge Branch

答案 8 :(得分:6)

要真正正确地执行合并,只需要从您正在合并的分支中输入 ,您就可以

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

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

git commit --amend

在我知道的任何场景中都不存在冲突,您不必进行额外的分支,它就像普通的合并提交一样。

然而,这与子模块不太匹配。

答案 9 :(得分:5)

请参阅Junio Hamano's widely cited answer:如果您要丢弃已提交的内容,只需丢弃提交内容,或者无论如何都要将其保留在主要历史记录之外。为什么将来每个人都在阅读提交无法提供的提交消息呢?

但有时会有行政要求,或者其他一些原因。对于那些你真的必须记录没有贡献的提交的情况,你想要:

(编辑:哇,我以前设法弄错了。这个有效。)

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

答案 10 :(得分:2)

这个使用git plumbing命令读取树,但缩短了整体工作流程。

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>

答案 11 :(得分:2)

  

为什么它不存在?

我在&#34; git command for making one branch like another&#34;如何模拟git merge -s theirs,请注意Git 2。5(2017年第4季度)现在更加清晰:

  

&#39; -X<option>&#39;的文档合并是误导性的   写这是为了表明&#34; -s theirs&#34;存在,但事实并非如此。

commit c25d98bJunio C Hamano (gitster)(2017年9月25日) Junio C Hamano -- gitster --合并于commit 4da3e23,2017年9月28日)

  

合并策略:避免暗示&#34; -s theirs&#34;存在

     

-Xours合并选项的说明有一个括号   这告诉读者它与-s ours非常不同,   这是正确的,但跟随它的-Xtheirs的描述   粗心地说&#34;这与ours&#34;相反,给出了错误   读者也需要警告它是非常的印象   不同于-s theirs,实际上甚至不存在。

-Xtheirs是一个应用于递归策略的策略选项。这意味着递归策略仍然可以合并它所能做的任何事情,并且只会回归到&#34; theirs&#34;在发生冲突时的逻辑。

关于theirs合并策略的针对性与否的争论最近被提起in this Sept. 2017 thread。 它承认older (2008) threads

  

简而言之,之前的讨论可以概括为“我们不想要&#39; -s theirs&#39;因为它鼓励错误的工作流程&#34;。

它提到了别名:

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

Yaroslav Halchenko试图再次倡导该战略,but Junio C. Hamano adds

  

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

     

一旦您确定他们的历史是主线,您宁愿将您的开发线视为一个侧分支并在该方向上进行合并,即生成的合并的第一个父级是提交他们的历史和第二个父母是你历史上最后一个坏人。所以你最终会使用&#34; checkout their-history && merge -s ours your-history&#34;至   保持第一父母身份合情合理。

     

此时,使用&#34; -s ours&#34;不再是缺少&#34; -s theirs&#34;的解决方法   它是所需语义的一个适当部分,即从幸存的规范历史记录​​的角度来看,你想要保留它所做的事情,取消其他历史记录所做的事情

答案 12 :(得分:0)

这会将你的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

答案 13 :(得分:0)

我认为你真正想要的是:

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

这看起来很笨拙,但它应该有效。唯一认为我真的不喜欢这个解决方案的是git历史会让人感到困惑......但至少历史记录会完全保留下来,你不需要为删除的文件做些特别的事情。

答案 14 :(得分:0)

等效(保留父订单)到&#39; git合并 - 他们的分支B&#39;

合并前:enter image description here

!!!确保你处于干净状态!!!

进行合并:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

我们做了什么?  我们创建了一个新的提交,我们和他们的两个父母和他们的提交的contnet是branchB - 他们的

合并后:enter image description here

更确切地说:

qry <- function(date_string)
{
    qry_string <- paste0("select xxxxx from yyy where date = '", date_string, "'")
    sqlQuery(datamart, qry_string, as.is=TRUE, stringsAsFactors=FALSE)
}

答案 15 :(得分:0)

此答案由Paul Pladijs给出。为了方便起见,我只是接受了他的命令并做了一个git别名。

编辑.gitconfig并添加以下内容:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

然后您可以通过运行以下命令来“ git merge -s他们的A”:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

答案 16 :(得分:-1)

我最近需要为两个共享历史记录的独立存储库执行此操作。我开始时:

  • Org/repository1 master
  • Org/repository2 master

我希望将repository2 master的所有更改应用于repository1 master,接受repository2将进行的所有更改。用git来说,这个应该是一个名为-s theirs的策略,但它不存在。要小心,因为-X theirs的名称就像你想要的那样,但它 NOT 是相同的(它甚至在手册页中也是如此)。

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

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

最后,您需要在repository1中发出合并请求以使其成为新的主服务器,或者只是将其保留为分支。

答案 17 :(得分:-1)

一种简单而直观的方法(在我看来)是两步操作

git checkout branchB .
git commit -m "Picked up the content from branchB"

之后

git merge -s ours branchB

(将两个分支标记为合并)

唯一的缺点是它不会从当前分支中删除在branchB中已删除的文件。之后,两个分支之间的简单差异将显示是否存在此类文件。

这种方法还可以在以后的修订日志中清楚地说明已完成的操作-以及预期的操作。