git中“我们的”和“他们的”的确切含义是什么?


323

这听起来像是一个问题的基本知识,但是我一直在寻找答案,现在我比以前更加困惑。

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

在合并冲突中,“我们的”是否总是显示两个版本中的较高者?

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

还是只使用分支名称(而不是说“我们的”,而要说“本地主人的”等)?

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

config.xml merge=ours

现在我结帐,将HEAD指向master,然后合并到test中。既然master是我们的,并且test的.gitattributes没有签出,它甚至会起作用吗?如果确实有效果,那么既然主人现在是我们的,那将会发生什么?

Answers:


374

我怀疑您在这里感到困惑,因为这从根本上来说是令人困惑的。更糟的是,当您进行基准调整时,我们/他们的整个工作切换角色(倒退)。

最终,在期间git merge,“我们的”分支是指您要合并的分支:

git checkout merge-into-ours

而“他们的”分支是指您要合并的(单个)分支:

git merge from-theirs

这里“我们”和“他们”有一定道理,因为,即使“他们”可能是你的,无论如何,“他们”是不是你是我的唯一,当你跑了git merge

虽然使用实际的分支名称可能很酷,但在更复杂的情况下会分崩离析。例如,代替上面的方法,您可以这样做:

git checkout ours
git merge 1234567

您通过原始提交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是您要从中合并的版本。


“我们的”和“他们的”概念在此期间rebase被交换的原因是,通过执行一系列的樱桃操作将改基工作到一个匿名分支中(分离的HEAD模式)。目标分支是匿名分支,而merge-from分支是您的原始(重新设置基准)分支:因此,“-我们的”表示正在建立匿名的一个基准,而“-他们的”表示“正在重新建立我们的分支” 。


至于gitattributes条目:它可能会产生影响:“我们的”实际上是在内部表示“使用阶段2”。但是,正如您所注意到的那样,它当时实际上并不存在,因此它在这里应该没有效果……好吧,除非您在开始之前将其复制到工作树中,否则不会有任何效果。

另外,顺便说一句,这适用于我们及其使用的所有用途,但有些是在整个文件级别上(-s ours对于合并策略;git checkout --ours在合并冲突期间),而有些是逐段的(-X ours-X theirs-s recursive合并)。这可能无助于解决任何混乱。

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


28
+1。关于我们以及他们在改组期间将被撤消的信息,另请参阅:stackoverflow.com/a/2960751/6309stackoverflow.com/a/3052118/6309
VonC 2014年

1
两件事相互“融合”。合并时,双方会相互“合并”。我认为说双方之一“没有合并成任何东西”是不正确的。如果不涉及分支名称(如您所指出的),则涉及提交名称(您可以说“ 7777777's”和“ 1234567's”,而不是“ ours”和“ theirs”)。我了解在调整基准期间会发生什么,而且我完全没有觉得这会造成混淆。我认为“ HEAD”和“传入”将比“我们的”和“他们的”更好,因为总有一个“ HEAD”(无论是否分离)。
CommaToast 2014年

15
我猜想,因为头部是思想的源泉,是身份的源泉,是自我的源泉,所以思考一下HEAD所指的“我的”(“我们的”,我猜我和头有两个)。如果仅此而已,那将只是一个不错的助记符设备。
CommaToast 2014年

1
话虽这么说,我仍然喜欢在做诸如变基之类的任何事情之前先对整个回购做一个物理副本...:D
CommaToast 2015年

3
“在这种情况下,不涉及分支名称!” ...因此,应改用commit comment / hash。不管它能得到什么。实际上,任何事情都比“我们的”和“他们的”好。我不知道这种困惑已经消失了数千个开发小时。git对C ++的“最令人烦恼的分析”的回答;)
Jarrod Smith,

49

Git中的“ 我们的 ”是指原始工作分支,该分支具有git历史的权威/规范部分。

他们的 ”指的是保存作品以便进行基础更改的版本(更改将被重播到当前分支上)。

这似乎交换给了一些人,这些人不知道进行重新基准化(例如git rebase)实际上搁置了您的工作(这是他们的工作),以便重播属于我们的规范/主要历史,因为我们正在重新基准化更改为第三方作品。

为文档git-checkout在GIT中被进一步澄清> = 2.5.1按f303016提交

--ours --theirs

从索引中检出路径时,请检出阶段2(“我们的”)或阶段3(“其”)的未合并路径。

请注意,在git rebase和期间git pull --rebase,“我们的”和“他们的”可能会互换。--ours给出更改所基于--theirs的分支的版本,同时给出保存要重新建立工作的分支的版本。

这是因为rebase用于工作流中,该工作流将远程站点上的历史记录视为共享规范,并将您要重新部署的分支上完成的工作视为要集成的第三方工作,并且您暂时承担了改组期间的规范历史的维护者。作为规范历史的保存者,您需要从远程将历史记录ours(即“我们共享的规范历史”)查看,而您在分支机构上theirs所做的工作(即“在此基础上的一个贡献者的工作”)。

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

我们的

通过支持我们的版本,此选项可以强制自动解决冲突的大块。与其他树不冲突的更改将反映到合并结果中。对于二进制文件,全部内容都是从我们这边获取的。

这不应与我们的合并策略混淆,该策略甚至根本不看另一棵树包含的内容。它丢弃了另一棵树所做的一切,声明我们的历史包含其中发生的所有事件。

他们的

这与我们的相反。

此外,这里说明了如何使用它们:

合并机制(git mergegit pull命令)允许使用-soption 选择后端合并策略。某些策略也可以采取自己的选择,可以通过给和和或作为-X<option>参数来传递它们。git mergegit pull


因此有时可能会令人困惑,例如:

  • git pull origin master这里 -Xours是我们的地方,-Xtheirs是他们(远程)分支
  • git pull origin master -r-Xours他们的(远程)在哪里,-Xtheirs我们的在哪里

因此,第二个示例与第一个示例相反,因为我们将分支重新建立在远程分支的顶部,所以我们的出发点是远程分支,而我们所做的更改被视为外部的。

git merge策略(-X ours-X theirs)类似。


2
这个答案似乎已经过时=>“ git merge --ours”不是有效的选项
Alexander Mills

@AlexanderMills答案没有谈git merge,但git pullgit checkout为例。如果您希望将此参数与一起使用git merge,则应使用-X ours。您仍然可以将--ours语法用于git checkout。我已经进一步澄清了答案。
kenorb '16

46

我知道已经解决了这个问题,但是这个问题使我困惑了很多次,我建立了一个小型参考网站来帮助我记住:https : //nitaym.github.io/ourstheirs/

以下是基本知识:

合并:

$ git checkout master 
$ git merge feature

如果要在中选择版本master

$ git checkout --ours codefile.js

如果要在中选择版本feature

$ git checkout --theirs codefile.js

变基:

$ git checkout feature 
$ git rebase master 

如果要在中选择版本master

$ git checkout --ours codefile.js

如果要在中选择版本feature

$ git checkout --theirs codefile.js

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


1
该网站非常有帮助。流程图样式和颜色编码的单词使网站比SO答案更易于理解。谢谢。
罗恩

10
  • 我们的:这是您当前所在的分支。
  • 他们的:这是您的操作中使用的另一个分支。

因此,如果您使用的是分支版本/2.5,并且将分支功能/新按钮合并到其中,那么发布/2.5中的内容就是我们所指的内容,而功能/新按钮上的内容就是他们所指的内容至。在合并操作期间,这非常简单。

大多数人唯一的问题是重新定案。如果执行重新基准而不是常规合并,则角色将互换。怎么样?好吧,这完全是由重新定基的方式引起的。考虑重新设计工作,像这样:

  1. 自上次拉取以来,您所做的所有提交都移到了自己的分支中,我们将其命名为BranchX
  2. 您签出当前分支的头,放弃您进行的所有本地更改,但以此方式检索其他人为该分支推送的所有更改。
  3. 现在,BranchX上的每个提交都是精心挑选的,以便从旧到新到您当前的分支。
  4. BranchX再次被删除,因此永远不会显示在任何历史记录中。

当然,这并不是真正发生的事情,但这对我来说是一个很好的思维模型。如果您看一下2和3,您将了解为什么现在要互换角色。从2开始,您当前的分支现在是服务器的分支,无需进行任何更改,因此这是我们的分支(您所在的分支)。您所做的更改现在位于当前分支(BranchX)以外的其他分支上,因此这些更改(尽管是您所做的更改)是它们的更改(您的操作中使用的另一个分支)。

这意味着如果您合并并且希望您的更改始终获胜,则会告诉git始终选择“我们的”,但是如果您重新定基并且希望所有更改都始终获胜,则会告诉git始终选择“他们的”。


3

我知道它并不能解释其含义,但是我为自己制作了一些图像,以提醒您使用哪个图像:

在此处输入图片说明

希望能帮助到你!

PS-也检查Nitay答案中的链接🙂


3

我将在这里张贴我的备忘录,因为我不得不一次又一次回到这里。

场景1.普通开发人员:您是不能合并masterfeature只能使用分支机构的开发人员。

情况1:主人是国王。您想要刷新feature分支(=重新设置为master),因为master其中包含依赖项的新更新,并且您想覆盖您的适度更改。

git checkout master
git pull

git checkout feature
git rebase -X ours master

情况2:您是国王。您想使feature分支基于master更改。但是您做得比同事更多,并且希望优先使用自己的更改。

git checkout master
git pull

git checkout feature
git rebase -X theirs master

重要提示:正如您所看到的,普通开发人员应该喜欢rebase每天练习和咖啡一样重复并重复一次。

场景2.合并感官:您是团队负责人,想合并其他分支并将合并后的结果直接推送给主管理员。master是您将要更改的分支。

情况1:主人是国王您想合并第三方分支,但这master是优先事项。feature是您上级所做的分支。

git checkout feature
git pull

git checkout master
git merge -X ours master

案例2:新的变更为王当您的高级开发人员发布新版本feature,您想覆盖master分支中的旧版本。

git checkout feature
git pull

git checkout master
git merge -X theirs master

记住:要在午夜该选记得masterours始终。并且theirsfeature他们所做的。


2

来自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 --theirs some_file,并将git checkout --ours some_file文件分别重置为当前版本和传入版本。

如果您已完成git checkout --ours some_filegit checkout --theirs some_file想要将文件重置为文件的三向合并版本,则可以执行git checkout --merge some_file

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.