这听起来可能是一个太基本的问题,但我一直在寻找答案,现在我比以前更困惑了。

当我的分支合并到我的另一个分支时,“我们的”和“他们的”在git中是什么意思? 两个分支都是“我们的”。

在合并冲突中,“我们的”总是显示两个版本的上部吗?

“我们的”是否总是指合并开始时HEAD所指向的分支?如果是这样,那么为什么不使用一个明确的所有格,如“当前分支的”,而不是使用一个所有格代词,如“我们的”,这是指模棱两可的(因为两个分支在技术上都是我们的)?

或者只是使用分支名称(而不是说“我们的”,而是说“本地主人的”或类似的)?

最让我困惑的部分是,如果我在一个特定分支的.gitattributes文件中指定。让我们说在测试分支中,我有以下.gitattributes文件:

config.xml merge=ours

现在我签出并点HEAD到master,然后在测试中合并。因为master是我们的,test的.gitattributes没有签出,它会有影响吗?如果真的有效果,既然师父现在是“我们的”了,那又会怎样呢?


当前回答

Git中的“our”指的是原始的工作分支,它在Git历史中具有权威/规范的部分。

“their”指的是保存工作以便重基于的版本(要在当前分支上重放的更改)。

这可能会被那些没有意识到做重基(例如git重基)实际上是在暂停你的工作(这是他们的),以便重放到我们的规范/主历史上,因为我们将我们的更改作为第三方工作重基。

Git -checkout的文档在Git >=2.5.1中根据f303016提交得到了进一步的澄清:

--ours --theirs When checking out paths from the index, check out stage #2 ('ours') or #3 ('theirs') for unmerged paths. Note that during git rebase and git pull --rebase, 'ours' and 'theirs' may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work that is being rebased. This is because rebase is used in a workflow that treats the history at the remote as the shared canonical one, and treats the work done on the branch you are rebasing as the third-party work to be integrated, and you are temporarily assuming the role of the keeper of the canonical history during the rebase. As the keeper of the canonical history, you need to view the history from the remote as ours (i.e. "our shared canonical history"), while what you did on your side branch as theirs (i.e. "one contributor's work on top of it").

对于git-merge,它的解释如下:

ours This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side. This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it. theirs This is the opposite of ours.

此外,这里解释了如何使用它们:

合并机制(git merge和git pull命令)允许使用-s选项选择后端合并策略。一些策略也可以有自己的选项,可以通过给git merge和/或git pull提供-X<option>参数来传递。


所以有时它会让人困惑,例如:

git将-Xours是我们的本地分支,- xtheir是他们的(远程)分支 git拉origin master -r where -Xours是他们的(远程),- xtheir是我们的

第二个例子与第一个相反,因为我们在远程分支的基础上重新建立了分支,所以我们的起点是远程分支,我们的更改被视为外部的。

git合并策略也类似(-X我们的和-X他们的)。

其他回答

我知道这个问题已经有答案了,但这个问题让我困惑了很多次,所以我建立了一个小的参考网站来帮助我记住: https://nitaym.github.io/ourstheirs/

以下是基本原则:

合并:

$ git checkout master 
$ git merge feature

如果你想在master中选择版本:

$ git checkout --ours codefile.js

如果您想在功能中选择版本:

$ git checkout --theirs codefile.js

重置:

$ git checkout feature 
$ git rebase master 

如果你想在master中选择版本:

$ git checkout --ours codefile.js

如果您想在功能中选择版本:

$ git checkout --theirs codefile.js

(当然,这是针对完整的文件)

没有精确的含义,因为这些术语的含义完全相反,这取决于你是在合并还是重基。思考两个分支的自然方式是“我的工作”和“别人的工作”。混淆这种分类的术语选择绝对是git中最糟糕的设计选择。它一定是受到了会计的“信用”和“借方”或“资产”和“负债”的启发——同样令人头疼。

我怀疑你在这里感到困惑,因为它从根本上令人困惑。更糟糕的是,当你在做rebase时,我们/他们的所有东西都转换了角色(变成了倒退)。

最终,在git合并过程中,“ours”分支指的是你要合并到的分支:

git checkout merge-into-ours

“their”分支指的是你要合并的(单个)分支:

git merge from-theirs

在这里,“ours”和“their”是有意义的,因为即使“their”可能是你的,“their”也不是你在运行git merge时使用的那个。

虽然使用实际的分支名称可能很酷,但在更复杂的情况下就不行了。例如,你可以这样做:

git checkout ours
git merge 1234567

通过原始commit-ID进行合并。更糟糕的是,你甚至可以这样做:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

在这种情况下,不涉及分支名称!

我认为这在这里没有什么帮助,但实际上,在gitrevisions语法中,您可以在冲突合并期间通过数字引用索引中的单个路径

git show :1:README
git show :2:README
git show :3:README

阶段#1是文件的共同祖先,阶段#2是目标分支版本,阶段#3是您要合并的版本。


“我们的”和“他们的”概念在改基过程中交换的原因是改基工作是通过做一系列的筛选,进入一个匿名分支(分离的HEAD模式)。目标分支是匿名分支,而merge-from分支是你的原始(预重基)分支:所以“——our”意味着匿名的一个重基正在构建,而“——their”意味着“我们的分支正在重基”。


至于gitattributes条目:它可能会产生影响:“ours”实际上在内部意味着“使用阶段#2”。但正如你所指出的,当时它还没有到位,所以它应该不会在这里产生影响……除非在开始之前将它复制到工作树中。

另外,顺便说一下,这适用于我们和他们的所有使用,但有些是在整个文件级别(-s我们的合并策略;git签出——在合并冲突时是我们的),有些是逐块的(在-s递归合并时是-X我们的或-X他们的)。这可能无助于解决任何困惑。

不过,我从来没有想过一个更好的名字。并且:参见VonC对另一个问题的回答,其中git mergetool为这些引入了更多的名称,称它们为“本地”和“远程”!

从git checkout的用法来看:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

在解决合并冲突时,你可以执行git checkout—他们的some_file和git checkout—我们的some_file来分别将文件重置为当前版本和传入版本。

如果你已经完成了git checkout——我们的some_file或git checkout——他们的some_file,并想要将文件重置为文件的3向合并版本,你可以执行git checkout——merge some_file。

澄清一下,如上所述,重基的意思是相反的,所以如果你看到

<<<<<<< HEAD
        foo = 12;
=======
        foo = 22;
>>>>>>> [your commit message]

使用'mine' -> foo = 12解决

解决使用'their ' -> foo = 22