代码之家  ›  专栏  ›  技术社区  ›  elmarco

有“他们的”版本的“Git Merge-s Ours”吗?

  •  730
  • elmarco  · 技术社区  · 17 年前

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

    我知道 git merge -s ours . 但我想要的是 git merge -s theirs .

    为什么它不存在?在与现有的冲突合并之后,我如何才能获得相同的结果 git 命令?( git checkout 来自b)的每个未合并文件

    更新:仅仅丢弃分支A(合并提交点到树的B版本)中的任何内容的“解决方案”并不是我要寻找的。

    17 回复  |  直到 7 年前
        1
  •  847
  •   Jason Aller    8 年前

    添加 -X 选择权 theirs . 例如:

    git checkout branchA
    git merge -X theirs branchB
    

    一切都将以理想的方式融合。

    我看到的唯一导致问题的原因是是否从BranchB中删除了文件。如果不是Git做了删除,它们就会显示为冲突。

    解决方法很简单。只是运行 git rm 使用已删除的任何文件的名称:

    git rm {DELETED-FILE-NAME}
    

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

    当然,使用 移除文件 命令将首先阻止冲突的发生。


    注释 :也存在较长的表单选项。要使用它,请更换:

    -X theirs
    

    用:

    --strategy-option=theirs
    
        2
  •  189
  •   Paul Pladijs    12 年前

    将branchB合并到已签出的branchA中的一个可能且经过测试的解决方案:

    # 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 .

        3
  •  82
  •   Jeff Puckett    7 年前

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

    git pull --strategy=theirs remote_branch
    

    但是这已经被删除了,正如这条消息中所解释的 Junio Hamano (Git维护人员)。如链接中所述,您可以这样做:

    git fetch origin
    git reset --hard origin
    

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

        4
  •  57
  •   musicmatze    13 年前

    从现在起我就用保罗·普拉迪杰的答案。我发现,你可以做一个“正常”的合并,发生冲突,所以你可以

    git checkout --theirs <file>
    

    通过使用另一个分支的修订来解决冲突。如果您对每个文件都这样做,那么您将拥有与预期相同的行为

    git merge <branch> -s theirs
    

    不管怎样,这比合并策略的效果要好!(这是用Git版本1.8.0测试的)

        5
  •  50
  •   Community Mohan Dere    9 年前

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

    尝试合并并使用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
    

    请注意,合并现在提交的第一个父级是来自 布兰奇 只有第二个来自 布兰查 . 这就是例如 Gandalf458's answer 做。

    仅使用B中的内容并保持正确的父顺序

    这是他们真正的版本 Git合并-我们的 “。它的内容与之前选项中的内容相同(即仅来自 布兰奇 )但是父母的顺序是正确的,即第一个父母来自 布兰查 第二个来自 布兰奇 .

    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 可以(不需要临时分支机构)。

        6
  •  21
  •   elmarco    17 年前

    我用

    git checkout -m old
    git checkout -b new B
    git merge -s ours old
    
        7
  •  14
  •   rafalmag Steve Kuo    14 年前

    如果您在分支机构A,请执行以下操作:

    git merge -s recursive -X theirs B
    

    在Git版本1.7.8上测试

        8
  •  8
  •   tshepang Arrie    11 年前

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

    我知道Git合并是我们的。但我想要的是类似于git merge>-s的。

    我假设您在master上创建了一个分支,现在希望合并回master,覆盖master中的任何旧内容。这正是我遇到这篇文章时想做的。

    做你想做的,除非先把一个分支合并到另一个分支。我刚刚做了这个,效果很好。

    git checkout Branch
    git merge master -s ours
    

    然后,签出master并将您的分支合并到其中(现在可以顺利进行):

    git checkout master
    git merge Branch
    
        9
  •  6
  •   Elijah Lynn    9 年前

    要真正正确地进行合并,需要 只有 来自要合并的分支的输入可以

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

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

    git commit --amend

    在我所知道的任何场景中都不会有冲突,您不必进行额外的分支,它就像一个正常的合并提交。

    不过,这对子模块不太好。

        10
  •  4
  •   jthill    11 年前

    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
    
        11
  •  2
  •   Michael R    11 年前

    这一个使用了git管道命令读取树,但缩短了整个工作流。

    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>
    
        12
  •  1
  •   VonC    8 年前

    为什么它不存在?

    当我提到 git command for making one branch like another “如何模拟 git merge -s theirs 请注意,2.15吉特(2017年第4季度)现在更清楚了:

    的文档 -X<option> 因为合并是错误的 书面建议” -s theirs “存在,但事实并非如此。

    commit c25d98b (2017年9月25日) Junio C Hamano ( gitster ) .
    (合并) Junio C Hamano -- gitster -- 在里面 commit 4da3e23 ,28 SEP 2017

    合并策略:避免暗示 -他们的 存在

    描述 -Xours 合并选项有附加说明 这告诉读者它与 -s ours , 是正确的,但是描述 -Xtheirs 随之而来 不小心说“这与 ours “,给出一个错误的 给读者的印象是,也需要提醒他们 不同于 -他们的 在现实中根本不存在。

    - X 是一个 战略选择 应用于递归策略。这意味着递归策略将仍然合并它可以合并的任何内容,并且只返回到“ theirs “发生冲突时的逻辑。

    是否有针对性的辩论 他们的 合并策略最近被重新引入 in this Sept. 2017 thread .
    它承认 older (2008) threads

    简而言之,前面的讨论可以总结为“我们不想要” -他们的 “因为它鼓励错误的工作流程”。

    它提到了别名:

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

    雅罗斯拉夫哈尔琴科试图再次倡导这一战略, but Junio C. Hamano adds :

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

    一旦你决定他们的历史是主线,你宁愿把你的发展线当作一个分支,朝着这个方向进行合并,也就是说,结果合并的第一个父级是对他们历史的提交,第二个父级是你历史中最后一个不好的父级。所以你最终会使用 checkout their-history && merge -s ours your-history “到 保持第一个家长的理智。

    在这一点上,使用 我们的 “不再是缺少的解决方案” -他们的 “。
    它是所需语义学的一个适当部分,也就是说,从幸存的规范历史行的角度来看,你想要保留它所做的,取消另一个历史行所做的。 .

        13
  •  0
  •   Pawan Maheshwari    13 年前

    这将合并现有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
    
        14
  •  0
  •   briemers    10 年前

    我认为你真正想要的是:

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

    这看起来很笨拙,但应该管用。我唯一不喜欢这个解决方案的是Git的历史会很混乱…但至少历史记录将被完全保留,您不需要为删除的文件做一些特殊的事情。

        15
  •  -1
  •   Trann    9 年前

    我最近只需要为两个共享同一历史的独立存储库执行此操作。我从以下开始:

    • Org/repository1 master
    • Org/repository2 master

    我想要所有的改变 repository2 master 应用于 repository1 master ,接受Repository2所做的所有更改。按照Git的说法,这个 应该 成为一种战略 -s theirs 但它并不存在。小心点,因为 -X theirs 它的名字和你想要的一样,但它是 不是 同样的(甚至在手册页上也这么说)。

    我解决这个问题的方法是 repository2 做一个新的分支 repo1-merge . 在那家分店,我跑了 git pull git@gitlab.com:Org/repository1 -s ours 它很好地融合了所有的问题。然后我把它推到遥控器上。

    然后我回到 repository1 做一个新的分支 repo2-merge . 在那家分店,我跑步 git pull git@gitlab.com:Org/repository2 repo1-merge 这将与问题一起完成。

    最后,您可能需要在 知识库1 让它成为新的主人,或者把它作为一个分支。

        16
  •  -1
  •   Boaz Nahum    8 年前

    相当于“git merge-s their branchb”的值(保持父级顺序)

    合并前: enter image description here

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

    合并:

    git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
    git reset --hard 36daf519952 # is the output of the prev command
    

    我们做了什么? 我们创造了一个新的承诺,我们的父母和他们的父母,承诺的内容是他们的分支。

    合并后: enter image description here

    更确切地说:

    git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'
    
        17
  •  -1
  •   rubund    7 年前

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

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

    然后

    git merge -s ours branchB
    

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

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

    这种方法还可以从随后的修订日志中清楚地看到已经做了什么——以及打算做什么。