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

我知道git合并是我们的。但我想要的是类似git merge -s的东西。

为什么它不存在?如何在与现有git命令冲突合并后实现相同的结果?(git从B中检出所有未合并的文件)

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


当前回答

这个答案是由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 their A”通过运行:

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

其他回答

当合并主题分支“B”在“A”使用git合并,我得到一些冲突。我知道所有的冲突都可以用“B”中的版本来解决。 我知道git合并是我们的。我想要的是git merge >-s their。

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

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

git checkout Branch
git merge master -s ours

然后,签出master并合并你的分支(现在会很顺利):

git checkout master
git merge Branch

请参阅Junio Hamano被广泛引用的答案:如果您要丢弃已提交的内容,那么只需丢弃提交,或者无论如何要将其排除在主历史记录之外。将来为什么要麻烦每个人从没有提供任何东西的提交中读取提交消息呢?

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

(编辑:哇,我以前错了吗?这个是可行的。)

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

这将合并现有的baseBranch中的newBranch

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

重新审视这个老问题,因为我刚刚找到了一个兼而有之的解决方案 简短而且——因为它只使用瓷器指令——容易理解。 明确地说,我想回答的问题在标题中提出 问题(实现git merge -s their),而不是问题体。在 换句话说,我想创建一个合并提交,它的树和 第二个父树:

# Start from the branch that is going to receive the merge.
git switch our_branch

# Create the merge commit, albeit with the wrong tree.
git merge -s ours their_branch

# Replace our working tree and our index with their tree.
git restore --source=their_branch --worktree --staged :/

# Put their tree in the merge commit.
git commit --amend

注意:git restore是git中引入的一个相当新的命令 2.23. Git帮助恢复警告

这个命令是实验性的。行为可能会改变。

我用多个版本的git (2.25.1, 2.30.2, 2.31.1, 2.34.1和2.35.1),并按预期工作。

为什么它不存在?

虽然我在“git命令使一个分支像另一个分支一样”中提到了如何模拟git合并-s,但请注意,git 2.15(2017年Q4)现在更清晰了:

用于合并的'-X<option>'的文档具有误导性 写的是“-s their”的存在,但事实并非如此。

参见Junio C Hamano (gitster)的commit c25d98b(2017年9月25日)。 (由Junio C Hamano—gitster—在commit 4da3e23,2017年9月28日合并)

合并策略:避免暗示“-s their”的存在 -Xours合并选项的说明有一个插入说明 这告诉读者,它与我们的-s非常不同, 这是正确的,但是后面的- xtheir的描述 不小心说“这是我们的相反”,给了一个错误 这种印象也需要提醒读者,它是非常的 不同于他们的-s,而后者在现实中根本不存在。

xtheir是一个应用于递归策略的策略选项。这意味着递归策略仍然会合并任何它可以合并的东西,并且只会在发生冲突时退回到“他们的”逻辑。

关于他们合并战略的相关性的争论最近在2017年9月的帖子中被重新提起。 它承认旧线程(2008年)

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

它提到了别名:

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

Yaroslav Halchenko试图再次倡导这一策略,但是Junio C. Hamano补充道:

The reason why ours and theirs are not symmetric is because you are you and not them---the control and ownership of our history and their history is not symmetric. Once you decide that their history is the mainline, you'd rather want to treat your line of development as a side branch and make a merge in that direction, i.e. the first parent of the resulting merge is a commit on their history and the second parent is the last bad one of your history. So you would end up using "checkout their-history && merge -s ours your-history" to keep the first-parenthood sensible. And at that point, use of "-s ours" is no longer a workaround for lack of "-s theirs". It is a proper part of the desired semantics, i.e. from the point of view of the surviving canonical history line, you want to preserve what it did, nullifying what the other line of history did.

正如Mike Beaton所评论的那样,Junio补充道:

Git merge -s ours <their-ref>有效地说“标记提交构成<their-ref>在他们的分支作为提交被永久忽略”; 这很重要,因为如果您随后从分支的后面的状态合并,它们后面的更改将被引入,而不会引入被忽略的更改。