这可能听起来像是一个基本问题,但我已经找到了答案,我现在比以前更加困惑。
将我的分支合并到我的另一个分支时,git中的“我们的”和“他们的”是什么意思? 两个分支都是“我们的”。
在合并冲突中,“我们的”总是显示两个版本的上部?
“我们的”总是指合并开始时HEAD指向的分支吗?如果是这样,为什么不使用像“当前分支”这样的明确的所有格引用,而不是使用像“我们的”这样的所有格代词,这些代词是引用模糊的(因为这两个分支在技术上都是我们的)?
或者只是使用分支名称(而不是说“我们的”只说“本地主人”等)?
对我来说最令人困惑的部分是我在特定分支的.gitattributes文件中指定。让我们说测试分支我有以下.gitattributes文件:
config.xml merge=ours
现在我结帐并将HEAD指向主,然后合并到测试。由于 master 是我们的,并且测试的.gitattributes没有签出,它甚至会产生影响吗?如果确实有影响,因为 master 现在是“我们的”,那么会发生什么?
答案 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
)。这可能无助于任何混乱。
git mergetool
为这些问题引入了更多名称,称之为"本地"和"远程"!
答案 1 :(得分:35)
Git中的“我们的”是指原始的工作分支,它具有git历史的权威/规范部分。
'他们的'指的是保存作品的版本rebased(要重播到当前分支的更改)。
这可能似乎与那些不知道进行变基(例如git rebase
)实际上暂停你的工作(这是他们的)以便重播的人交换规范/主要历史是我们的,因为我们将我们的变化重新定位为第三方工作。
根据f303016
commit,Git> = 2.5.1进一步阐明了git-checkout
的文档:
--ours
--theirs
检查索引中的路径时,请查看阶段#2 ('我们的')或#3('他们')用于未合并的路径。
请注意,在
git rebase
和git pull --rebase
期间,“我们的”和“他们的”可能会出现交换;--ours
提供更改所依据的分支的版本,而--theirs
提供保留您正在重新定位的工作的分支的版本。这是因为
rebase
用于将远程历史记录视为共享规范的工作流程,并将您要重新分支的分支上的工作视为要集成的第三方工作,并且你在rebase期间暂时扮演规范历史守护者的角色。作为规范历史的守护者,您需要将远程历史记录视为ours
(即“我们共享的规范历史记录”),而您在旁边的分支视为theirs
(即“一个贡献者在其上面的工作“)。
对于git-merge
,它可以通过以下方式解释:
<强>我们强>
此选项通过支持我们的版本,强制冲突的帅哥干净利落地自动解决。来自与我们方不冲突的其他树的更改将反映到合并结果中。对于二进制文件,整个内容都来自我们这边。
这不应该与我们的合并策略相混淆,合并策略甚至不会查看其他树包含的内容。它丢弃了另一棵树所做的一切,宣告我们的历史包含了所有发生的事情。
<强>他们强>
这与我们的相反。
此外,还解释了如何使用它们:
合并机制(
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
)。
答案 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)
答案 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:大师为王您想合并第三方分支机构,但是优先级为master
。 feature
是您的上级所做的分支。
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
总是ours
。 theirs
是他们所做的feature
。
答案 5 :(得分:2)
因此,如果您在分支 release / 2.5 上并将分支功能/新按钮合并到其中,那么 release / 2.5中的内容是我们的所指的内容, feature / new-buttons 中的内容是他们的所指的内容。在合并行动期间,这非常简单。
大多数人唯一的问题是 rebase case 。如果执行重新基础而不是正常合并,则会交换角色。怎么样?那么,这完全是由于变革的运作方式造成的。想想rebase能像那样工作:
当然,这并不是真正发生的事情,但它对我来说是一个不错的心灵模型。如果你看看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_file
和git checkout --ours some_file
分别将文件重置为当前版本和传入版本。
如果您已经完成git checkout --ours some_file
或git 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中最糟糕的设计选择。它一定是受到会计的“贷方”和“借方”或“资产”和“负债”的启发-同样令人头疼。