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

Posted

技术标签:

【中文标题】git中“我们的”和“他们的”的确切含义是啥?【英文标题】:What is the precise meaning of "ours" and "theirs" in git?git中“我们的”和“他们的”的确切含义是什么? 【发布时间】:2014-10-23 22:42:04 【问题描述】:

这听起来可能是一个太基本的问题,但我已经搜索过答案,现在比以前更困惑了。

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

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

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

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

对我来说最令人困惑的部分是如果我在特定分支的 .gitattributes 文件中指定。假设在 test 分支 我有以下 .gitattributes 文件:

config.xml merge=ours

现在我结帐并将 HEAD 指向 ma​​ster,然后合并到 test。既然 ma​​ster 是我们的,而 test 的 .gitattributes 并没有检出,那它还会有效果吗?如果确实有效果,既然 ma​​ster 现在是“我们的”,那会发生什么?

【问题讨论】:

另见:Who is "us" and who is "them" according to Git? 我有一个答案,在那里我详细解释了什么是 us / oursthem / 他们的以及他们的意思/他们如何改变git mergegit cherry-pickgit rebasegit revert 见鬼。想出这个名字的人应该是在淘气的凳子上;这太模棱两可了。 天啊,谢谢你发布这个。想出这个名字的人也很困惑。 【参考方案1】:

只是澄清一下 -- 如上所述,当 rebase 意义是相反的,所以如果你看到

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

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

使用“他们的”解决 -> foo = 22

【讨论】:

【参考方案2】:

我会在这里发布我的备忘录,因为我必须一次又一次地回到这里。

场景 1. 普通开发者:您是无法合并到 master 并且只能使用 feature 分支的开发者。

案例 1:master is a king. 你想刷新你的 feature 分支(= rebase 到 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. Merging-sensei:您是团队负责人,想要合并其他分支并将合并的结果直接推送给 master。 master 是您将更改的分支。

案例一:master为王你想合并第三方分支,但master优先。 feature是你前辈做的一个分支。

git checkout feature
git pull

git checkout master
git merge -X ours feature

案例 2:新变化为王 当您的高级开发人员发布了一个很酷的 feature 并且您想覆盖 master 分支中的旧 s**t。

git checkout feature
git pull

git checkout master
git merge -X theirs feature

记住:要记住在午夜选择哪一个:master 总是 ours。而theirs 是他们的feature

【讨论】:

注意: -X 表示 --strategy-option 并允许支持来自 theirsours 的代码【参考方案3】:

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

【讨论】:

我不同意,有一个精确的意思:“我们的”意思是“HEAD 在哪里”,在合并或变基中:***.com/a/2960751/6309 “HEAD 在哪里”是一个以工具为中心而非以用户为中心的概念。这正是问题所在。 我现在明白你的观点了。您是对的,尽管从这个角度来看(工具与用户),确实有很多有问题的设计决策。有些正在改进:git checkout vs. git switch/git restore 浮现在脑海中。【参考方案4】:

我知道它没有解释含义,但我给自己做了一个小图像,作为提醒使用哪一个的参考:

希望对你有帮助!

PS - 还要检查Nitay's answer中的链接?

【讨论】:

我花了太长时间阅读这些巨大的答案书籍,您的形象虽然不完美,但以更简洁的方式对我进行了近乎完美的解释。版本 2 可以在此上下文中直观地使用 HEAD 一词的解释 感谢赞美!我很高兴它帮助了其他人,因为它在视觉上帮助了我!我省略了 HEAD 因为它是与时间相关的信息,是特定时刻的指针。我想通过这张图片给出一个“永恒”的观点;尽管我认为对于 git 新人来说掌握起来并不明显。为了解释/显示HEAD,我需要为每个git .. 命令显示一个(在checkouts 之后,merge 之后,rebase 之后);恕我直言,这可能会导致图像更加混乱;所以我理所当然地认为一个人已经具备 historyHEADcheckoutmerge变基.【参考方案5】:

来自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

【讨论】:

【参考方案6】:

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

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

【讨论】:

那个网站非常有用。流程图样式和颜色编码的文字使网站比 SO 答案更容易理解。谢谢。 谢谢,这是我正在寻找的简单示例解释。其他答案过多地谈论了您可能会感到困惑的原因,以及这些术语的含义等等,以至于答案本身变得令人困惑。 这个答案是黄金。每次在 rebase 合并冲突期间我必须做我们/他们的事情时,我都会继续回答这个问题。【参考方案7】: 我们的:这是你目前所在的分支。 他们的:这是你的行动中使用的另一个分支。

因此,如果您在分支 release/2.5 上并将分支 feature/new-buttons 合并到其中,那么在 release/2.5 中找到的内容ours 所指的内容,feature/new-buttons 上的内容是 theirs 所指的内容。在合并操作期间,这非常简单。

大多数人会遇到的唯一问题是rebase case。如果您执行 re-base 而不是正常的合并,则会交换角色。怎么样?好吧,这完全是由变基的工作方式引起的。想想 rebase 像这样工作:

    自上次拉取以来您所做的所有提交都将移至它们自己的分支,我们将其命名为 BranchX。 您签出当前分支的负责人,丢弃任何本地 您所做的更改,但这样可以检索其他人为该分支推送的所有更改。 现在,BranchX 上的每个提交都会按照从旧到新到当前分支的顺序进行精心挑选。 BranchX 再次被删除,因此永远不会出现在任何历史记录中。

当然,这并不是真正发生的事情,但对我来说这是一个很好的思维模型。如果你看一下 2 和 3,你就会明白为什么现在角色互换了。从 2 开始,您当前的分支现在是来自服务器的分支,没有任何更改,所以这是 ours(您所在的分支)。您所做的更改现在位于一个不同的分支上,而不是您当前的分支 (BranchX),因此这些更改(尽管是您所做的更改)是 他们的(另一个您的操作中使用的分支)。

这意味着如果你合并并且你希望你的更改总是获胜,你会告诉 git 总是选择“我们的”,但是如果你变基并且你希望你的所有更改总是获胜,你告诉 git 总是选择“他们的” ”。

【讨论】:

【参考方案8】:

我怀疑您在这里感到困惑,因为它从根本上令人困惑。更糟糕的是,当您进行变基时,整个我们/他们的东西都会转换角色(变回)。

最终,在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 syntax 中,您可以在冲突合并期间按编号引用索引中的单个路径

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

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


“我们的”和“他们的”概念在rebase 期间被交换的原因是,rebase 的工作原理是通过一系列的挑选,进入一个匿名分支(分离的 HEAD 模式)。目标分支是匿名分支,merge-from 分支是您的原始(预变基)分支:所以“--ours”表示正在构建的匿名变基,而“--theirs”表示“我们的分支正在变基” .


至于 gitattributes 条目:它可能有效果:“我们的”在内部实际上意味着“使用第 2 阶段”。但正如您所注意到的,它当时实际上并没有到位,所以它不应该在这里产生影响......好吧,除非你在开始之前将它复制到工作树中。

另外,顺便说一句,这适用于我们和他们的所有用途,但有些是在整个文件级别(-s ours 用于合并策略;git checkout --ours 在合并冲突期间),有些是在一个片段上逐个(-X ours-X theirs-s recursive 合并期间)。这可能对任何混淆都没有帮助。

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

【讨论】:

天啊。谢谢托雷克。我正处于一个变基的中间,我不明白为什么我对分支的更改不在 @torek,这一定是我遇到的对此最好的解释之一。感谢您在此回复中付出如此多的思考和努力,这非常有帮助。【参考方案9】:

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

他们的”指的是保存工作的版本,以便成为rebased(更改将重播到当前分支)。

这似乎被替换为那些不知道进行变基(例如git rebase)实际上是暂停您的工作(这是他们的)以重播规范的人/main 历史是我们的,因为我们将我们的更改重新定位为第三方工作。

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

--ours --theirs

从索引中检查路径时,检查阶段 #2 ('ours') 或 #3 ('theirs') 用于未合并的路径。

请注意,在git rebasegit pull --rebase 期间,“我们的”和“他们的”可能会互换; --ours 给出了更改被重新定位到的分支中的版本,而--theirs 给出了包含正在被重新定位的工作的分支的版本。

这是因为rebase 用于将远程历史记录视为共享规范历史的工作流中,并将在您正在变基的分支上完成的工作视为要集成的第三方工作,并且您在 rebase 期间暂时担任规范历史的守护者的角色。作为规范历史的保存者,您需要从远程查看历史记录为ours(即“我们共享的规范历史”),而您在分支上所做的工作为theirs(即“一位贡献者在最重要的”)。

对于git-merge,解释如下:

我们的

此选项强制通过支持我们的版本来干净地自动解决冲突的大块。与我们这边不冲突的另一棵树的更改会反映到合并结果中。对于二进制文件,全部内容都取自我们这边。

这不应与 ours 合并策略混淆,后者甚至根本不查看其他树包含的内容。它丢弃了其他树所做的一切,声明我们的历史包含其中发生的一切。

他们的

这与我们的相反。

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

合并机制(git mergegit pull 命令)允许使用-s 选项选择后端合并策略。一些策略也可以采用自己的选项,可以通过将 -X&lt;option&gt; 参数传递给 git merge 和/或 git pull 来传递。


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

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

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

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

【讨论】:

这个答案似乎过时了 => "git merge --ours" 不是一个有效的选项 @AlexanderMills 答案没有提到git merge,而是以git pullgit checkout 为例。如果您想将此参数与git merge 一起使用,则应使用-X ours。对于git checkout,您仍然可以使用--ours 语法。我已经进一步澄清了答案。 您对变基方式向后的解释非常有道理,我可能不用谷歌搜索就能记住它。谢谢你!

以上是关于git中“我们的”和“他们的”的确切含义是啥?的主要内容,如果未能解决你的问题,请参考以下文章

编程中“厨房水槽”的确切含义是啥?

JPA @Entity 注解的确切含义是啥?

IFS=$'\n' 的确切含义是啥?

IFS=$'\n' 的确切含义是啥?

依赖范围的确切含义是啥,例如构建、测试等

Angular 2\TypeScript 中 export 关键字的确切含义是啥?