"我们的"的确切含义是什么?和#34;他们的"在git?

时间:2014-08-29 21:18:50

标签: git merge

这可能听起来像是一个基本问题,但我已经找到了答案,我现在比以前更加困惑。

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

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

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

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

对我来说最令人困惑的部分是我在特定分支的.gitattributes文件中指定。让我们说测试分支我有以下.gitattributes文件:

config.xml merge=ours

现在我结帐并将HEAD指向,然后合并到测试。由于 master 是我们的,并且测试的.gitattributes没有签出,它甚至会产生影响吗?如果确实有影响,因为 master 现在是“我们的”,那么会发生什么?

9 个答案:

答案 0 :(得分:294)

我怀疑你在这里感到困惑,因为它从根本上引起了混乱。更糟糕的是,当你做一次变装时,我们/他们的整个东西会转换角色(变得倒退)。

最终,在git merge期间,"我们的" branch是指您将合并到

的分支
git checkout merge-into-ours

和"他们的" branch指的是您正在合并的(单个)分支:

git merge from-theirs

在这里"我们的"和#34;他们的"有道理,即使他们的#34;他们的#34;无论如何,可能是你的,"他们的"当您运行git merge时,不是您 的那个。

虽然使用实际的分支名称可能非常酷,但在更复杂的情况下会崩溃。例如,您可以执行以下操作,而不是上述内容:

git checkout ours
git merge 1234567

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

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

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

我认为这里有点帮助,但事实上,在gitrevisions syntax中,您可以在冲突合并期间按编号引用索引中的单个路径

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

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


"我们的"和#34;他们的"在rebase期间交换的概念是,rebase通过执行一系列樱桃选择而进入匿名分支(分离的HEAD模式)。目标分支是匿名分支,而merge-from分支是您的原始(预先变更)分支:所以" - 我们的"意味着匿名的一个rebase正在建设,而#34; - 他们的"意味着"我们的分支被重新定位"。


至于gitattributes条目:可能有效:"我们的"真的意味着"使用阶段#2"内部。但正如你所注意到的那样,它当时并不存在,所以它不应该在这里产生效果......好吧,除非你在开始之前将它复制到工作树中

顺便说一下,这适用于我们和他们的所有用途,但有些用于整个文件级别(-s ours用于合并策略; git checkout --ours在合并冲突期间)和一些在-X ours合并期间逐个进行(-X theirs-s recursive)。这可能无助于任何混乱。

但是,我从未想过这些更好的名字。并且:请参阅VonC's answer另一个问题,其中git mergetool为这些问题引入了更多名称,称之为"本地"和"远程"!

答案 1 :(得分:35)

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

'他们的'指的是保存作品的版本rebased(要重播到当前分支的更改)。

这可能似乎与那些不知道进行变基(例如git rebase)实际上暂停你的工作(这是他们的)以便重播的人交换规范/主要历史是我们的,因为我们将我们的变化重新定位为第三方工作。

根据f303016 commit,Git> = 2.5.1进一步阐明了git-checkout的文档:

  

--ours   --theirs

     

检查索引中的路径时,请查看阶段#2         ('我们的')或#3('他们')用于未合并的路径。

     

请注意,在git rebasegit pull --rebase期间,“我们的”和“他们的”可能会出现交换; --ours提供更改所依据的分支的版本,而--theirs提供保留您正在重新定位的工作的分支的版本。

     

这是因为rebase用于将远程历史记录视为共享规范的工作流程,并将您要重新分支的分支上的工作视为要集成的第三方工作,并且你在rebase期间暂时扮演规范历史守护者的角色。作为规范历史的守护者,您需要将远程历史记录视为ours(即“我们共享的规范历史记录​​”),而您在旁边的分支视为theirs(即“一个贡献者在其上面的工作“)。

对于git-merge,它可以通过以下方式解释:

  

<强>我们

     

此选项通过支持我们的版本,强制冲突的帅哥干净利落地自动解决。来自与我们方不冲突的其他树的更改将反映到合并结果中。对于二进制文件,整个内容都来自我们这边。

     

这不应该与我们的合并策略相混淆,合并策略甚至不会查看其他树包含的内容。它丢弃了另一棵树所做的一切,宣告我们的历史包含了所有发生的事情。

     

<强>他们

     

这与我们的相反。

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

  

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

所以有时它可能会让人感到困惑,例如:

  • git pull origin master其中-Xours是我们的本地,-Xtheirs是他们的(远程)分支
  • git pull origin master -r其中-Xours是他们的(远程),-Xtheirs是我们的

所以第二个例子与第一个例子相反,因为我们将我们的分支重新定位在远程分支之上,所以我们的起点是远程分支,我们的变化被视为外部。

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

答案 2 :(得分:22)

我知道这已经得到了解答,但这个问题让我困惑了很多次,我已经建立了一个小型参考网站来帮助我记住: 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

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

答案 3 :(得分:10)

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

here

希望有帮助!

PS-还检查enter image description here?

中的链接

答案 4 :(得分:5)

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

场景1.普通开发人员:您是不能合并到master的开发人员,只需要玩feature个分支。

案例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:大师为王您想合并第三方分支机构,但是优先级为masterfeature是您的上级所做的分支。

git checkout feature
git pull

git checkout master
git merge -X ours feature

案例2:新变化为王 当您的高级开发人员发布了一个不错的feature并想覆盖master分支中的旧版本时。

git checkout feature
git pull

git checkout master
git merge -X theirs feature

记住:要记住在午夜时选择哪个:master总是ourstheirs是他们所做的feature

答案 5 :(得分:2)

  • 我们的:这是您目前所在的分行。
  • 他们的:这是您的行动中使用的另一个分支。

因此,如果您在分支 release / 2.5 上并将分支功能/新按钮合并到其中,那么 release / 2.5中的内容我们的所指的内容, feature / new-buttons 中的内容是他们的所指的内容。在合并行动期间,这非常简单。

大多数人唯一的问题是 rebase case 。如果执行重新基础而不是正常合并,则会交换角色。怎么样?那么,这完全是由于变革的运作方式造成的。想想rebase能像那样工作:

  1. 自上次提取以来您所做的所有提交都已移至自己的分支,我们将其命名为 BranchX
  2. 您结帐当前分行的负责人,丢弃任何本地分行   您所做的更改,但这样可以检索其他人为该分支推送的所有更改。
  3. 现在对 BranchX 的每次提交都是挑选出来的,以便从当前分支到新旧。
  4. BranchX 会再次被删除,因此无法在任何历史记录中显示。
  5. 当然,这并不是真正发生的事情,但它对我来说是一个不错的心灵模型。如果你看看2和3,你就会明白为什么角色现在被交换了。从2开始,您当前的分支现在是服务器的分支,没有任何更改,因此这是我们的(您所在的分支)。您所做的更改现在位于不是当前分支( BranchX )的不同分支上,因此这些更改(尽管是您所做的更改)是他们的(另一个)在你的行动中使用的分支。)

    这意味着如果您合并并且您希望您的更改始终获胜,那么您应该告诉git始终选择&#34;我们的&#34;但如果你想要改变并且你希望所有的改变总能获胜,你就告诉git总是选择&#34;他们的#34;。

答案 6 :(得分:1)

根据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_filegit checkout --ours some_file分别将文件重置为当前版本和传入版本。

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

答案 7 :(得分:1)

只是为了澄清 - 如上所述,当重新定位时,意义是相反的,所以如果你看到

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

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

使用'theirs'解析-> foo = 22

答案 8 :(得分:0)

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