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 指向 master,然后合并到 test。既然 master 是我们的,而 test 的 .gitattributes 并没有检出,那它还会有效果吗?如果确实有效果,既然 master 现在是“我们的”,那会发生什么?
【问题讨论】:
另见:Who is "us" and who is "them" according to Git? 我有一个答案,在那里我详细解释了什么是 us / ours 和 them / 他们的以及他们的意思/他们如何改变git merge
、git cherry-pick
、git rebase
和git 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
并允许支持来自 theirs
或 ours
的代码【参考方案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 ..
命令显示一个(在checkout
s 之后,merge
之后,rebase
之后);恕我直言,这可能会导致图像更加混乱;所以我理所当然地认为一个人已经具备 history、HEAD、checkout、merge 和变基.【参考方案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_file
和git checkout --ours some_file
将文件分别重置为当前版本和传入版本。
如果您已完成 git checkout --ours some_file
或 git 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 rebase
和git pull --rebase
期间,“我们的”和“他们的”可能会互换;--ours
给出了更改被重新定位到的分支中的版本,而--theirs
给出了包含正在被重新定位的工作的分支的版本。这是因为
rebase
用于将远程历史记录视为共享规范历史的工作流中,并将在您正在变基的分支上完成的工作视为要集成的第三方工作,并且您在 rebase 期间暂时担任规范历史的守护者的角色。作为规范历史的保存者,您需要从远程查看历史记录为ours
(即“我们共享的规范历史”),而您在分支上所做的工作为theirs
(即“一位贡献者在最重要的”)。
对于git-merge
,解释如下:
我们的
此选项强制通过支持我们的版本来干净地自动解决冲突的大块。与我们这边不冲突的另一棵树的更改会反映到合并结果中。对于二进制文件,全部内容都取自我们这边。
这不应与 ours 合并策略混淆,后者甚至根本不查看其他树包含的内容。它丢弃了其他树所做的一切,声明我们的历史包含其中发生的一切。
他们的
这与我们的相反。
此外,这里解释了如何使用它们:
合并机制(
git merge
和git 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
)。
【讨论】:
这个答案似乎过时了 => "git merge --ours" 不是一个有效的选项 @AlexanderMills 答案没有提到git merge
,而是以git pull
和git checkout
为例。如果您想将此参数与git merge
一起使用,则应使用-X ours
。对于git checkout
,您仍然可以使用--ours
语法。我已经进一步澄清了答案。
您对变基方式向后的解释非常有道理,我可能不用谷歌搜索就能记住它。谢谢你!以上是关于git中“我们的”和“他们的”的确切含义是啥?的主要内容,如果未能解决你的问题,请参考以下文章