以下是这种情况:
我创建了一些文件,以便在我的分支中使用其他代码。这只是一个快速解决方案 - 同时一位同事也创建并处理了这些文件。因此,当我合并代码时,我会收到这些文件的both added
消息。
我想放弃我的文件版本 - 我不想推翻它们。
在这些文档上使用git rm <file>
会删除我的文件版本还是从repo / project中删除文件?
我能解决这个问题的最佳方法是什么(我已经读过我们/他们的,但对我来说没有意义)?
答案 0 :(得分:1)
通过阅读here和here,可以将此答案放在一起。在Git合并中,ours
分支通常是指合并发生的目标分支。 theirs
通常指的是合并到目标中的单个分支。根据您的分支(包含要保留的新添加文件的版本)是目标还是单个分支,您可能希望在遇到合并冲突后执行以下操作之一:
git checkout --ours path/to/some/file
git checkout --theirs path/to/some/file
正如您正确指出的那样,如果您执行git rm <file>
,则会删除该文件的两个版本,可能不是您想要的版本。
答案 1 :(得分:1)
由于您要放弃您的文件版本,您需要:
git checkout --theirs <file>
git add <file>
这告诉Git将您的工作(创建新版本的文件)与其工作相结合的正确解决方案(创建不同新版本的文件)是使用他们的文件版本。
鉴于Git的术语是一个问题(对很多人来说都是如此),你在这里应该做的就是学习术语。所以,让我们来看看。
首先,不要将您的存储库视为持有文件。它确实如此,但是这样思考它并不能让你在任何地方找到它 - 就像试图把你的房子当作持有插座和门把手等等。考虑它是错误的。您的房子包含房间,它是带有门把手的房间,以及插入电器和手机充电器的插座,等等。就像'#34; house&#34;是&#34; rooms&#34;,存储库的有趣级别是提交。 (不管是房子井,还是任何实用房子 - 你只需要或多或少地永久地向存储库添加新的提交,而不会丢弃任何旧的提交。 ,大多数!真的很难摆脱提交,但可以做到。)
因此,您的存储库包含大量提交。每个提交都包含一些文件,我们马上就会知道,但存储库本身就是提交的。
大多数提交都非常简单:它们有一组文件 - 源树快照 - 以及一些元数据,例如&#34;此提交是由AU Thor&lt; thor@example.com&gt;&#34; 。几乎每次提交的元数据的关键部分之一是其父提交的哈希ID 。这是托尔先生(或其他任何人)创造一个新承诺之前的承诺。 (例如,把它看作进入前一个房间的门。)所以提交:
Git 通过哈希ID 找到提交,这是git log
打印的那个看似随意的大丑:
$ git log
commit 3e5524907b43337e82a24afbc822078daf7a868f
Author: Junio C Hamano <...
这些哈希ID是每个提交的真实名称。每个提交都有一个独特的提交。它们对大多数人来说都毫无用处,但是Git使用它们来查找每次提交所需的所有数据。此特定提交的父级为e66e8f9be8af90671b85a758b62610bd1162de2d
,因此此提交 - 此3e5524907...
部分地说my parent is e668ef9be8...
。 (当看到这些丑陋的身份证时,他的眼睛往往会茫然。幸运的是,作为人类,我们主要忽略它们。)
当您运行git checkout somebranch
时,Git所做的是将分支名称转换为哈希ID,然后从该提交中提取所有文件,以便您可以使用它们或对它们进行处理。它还将当前提交的概念设置为任何哈希ID,并将当前分支名称的概念设置为您提供的名称。正在运行git status
会告诉您on branch somebranch
,所以现在您正在&#34; on&#34;该分支 - 这部分意味着您签出了一些特定的提交哈希ID。
现在您已经检查了一些提交,当您在存储库中工作时,您正在做的是决定您将提交的某些文件中的内容。完成每次新提交后,您将永久地将所有文件冻结到该提交中,作为新快照,以该形式。如果您删除文件并进行提交,则创建一个新的提交/快照,其中包含少量文件,而不会更改任何先前的提交。
Git从临时区域创建这些快照,它也称为索引,有时也称为缓存。这些只是同一件事的三个名字,要么是因为它如此重要(它是这样),要么是因为Linus使用的第一个名字,&#34; index&#34;,就是这么糟糕的名字(在我的名字中)意见,它并不好,但它并不是那么糟糕)。这个临时区域通常几乎是不可见的:你实际上并没有直接看到它。相反,您可以使用Git称为工作树或工作树或工作目录的工作。在这个领域,文件只是文件 - 它们并不是奇怪的特殊Git实体。
在索引/登台区域和提交中,文件很奇怪和特殊:大多数情况下,它们会被压缩以节省空间。在提交中,它们也是只读的:你不能改变任何现有的提交,甚至不能改变一点。您可以使用git add
从工作树区域复制普通文件,覆盖索引中的文件。这就是您完成更改的方式:您在工作树中处理该文件,然后运行git add file
。
如果您拥有所需的所有文件,并将它们复制到暂存区域以覆盖以前的副本,则运行git commit
让Git进行新的提交。 Git冻结所有文件的索引副本 - 包括你没有覆盖的文件 - 并将它们全部放入新的提交中。您是新提交的作者。新提交的父提交是您之前通过运行git checkout
提取的提交。
解决合并冲突时也是如此。你正在做的是决定哪些文件,哪些内容将进入下一次提交。但是在这段时间里有一些特别的东西。
首先,您所做的下一次提交将是合并提交,也就是说,提交多个父。而不只是说我的一个父母是&lt;大丑陋的ID&gt; ,它会说:我的两个父母是&lt;第一个丑陋的ID&gt;和&lt;第二个丑陋的ID&gt; 。 Git在内部使用它来知道这实际上是一个合并,并且能够跟踪提交的历史两个作者:你的工作,以及其他任何人的工作,结合起来在合并时,你决定合并后的结果是什么,但Git为子孙后代记录了你提交的两个这一事实。
在这个冲突合并期间发生的第二个特殊事情是索引 - 记住,这是暂存区域,您正在构建下一个合并提交以进行扩展的地方!通常,您的索引只包含每个文件的一个副本。但是当您进行合并时,您的索引最多可以保存每个冲突文件的三个副本!您可以同时拥有三个README.md
个文件。 (我在这里假设冲突大约是README.md
。可能该文件有一些其他名称,但它们都是一样的。)
从技术上讲,这些多个版本称为更高阶段条目。大多数情况下,你不必关心这一点;你只需要关心你的索引是否对某些文件有这种状态。
您的工作树无法解决这个&#34;一个文件的多个版本&#34;技巧,你的最终提交也只能有一个README.md
。因此,这个特殊的索引状态,它有多个文件,是你必须修复的东西。完成合并README.md
后,您可以选择在索引中包含一个 README.md
,或者否 README.md
指数。无论你做出哪个选择,当你运行git commit
时,Git都会将其冻结到新的提交中。
这是关联的问题和答案。索引保存文件的两个版本:你和他们的。你可以:
使用工作树创建正确或组合的文件,并git add
结果。这会覆盖README.md
的所有冲突的多个版本,因此索引只有一个README.md
。
使用git checkout --ours
将您的README.md
版本从索引中提取到工作树中。索引仍然包含所有版本,但现在工作树文件是您的版本。
使用git checkout --theirs
从索引中将README.md
的版本提取到工作树中。和以前一样,索引仍然包含所有版本,但现在工作树文件是他们的版本。
如果您选择这两个git checkout
选项中的一个,则可以返回第一个选项 - git add
- 复制工作树文件,现在只是其中之一,进入索引,消灭其他版本。
或者,您可以在该文件上运行git rm
。这将从索引中删除所有版本,因此索引现在否 README.md
。如果您已完成解决所有冲突,您现在可以git commit
;这个新提交没有README.md
。正如我们已经看到的,这不会影响任何以前的提交,但它确实意味着您声明了将 README.md
和组合起来的正确方法他们的 README.md
将完全删除该文件。
如果这是错误的答案 - 如果你想保留他们的版本,例如 - 不要这样做。
无论如何,一旦你完成所有文件的解析,你就像往常一样运行git commit
。这使得新的合并提交,然后更改分支名称本身 - 存储在您所依赖的分支名称下的哈希ID,即 - 它会记住您的新提交。这就是分支如何增长:一个新的提交将旧的分支提示作为其父级,或者用于合并,它是其两个父级中的第一个。新提交的新生成的唯一ID将进入分支名称。因此,如果你有:
...--o--o--o <-- yourfix (HEAD)
\
o--o--o <-- origin/theirfix
并且您运行git merge origin/theirfix
并遇到合并冲突并解决并提交,最终结果是:
...--o--o--o---M <-- yourfix (HEAD)
\ /
o--o--o <-- origin/theirfix
请注意,新提交(此处为Merge标记为M
)已添加到您自己的分支名称yourfix
,凭借更改存储在其下的哈希ID名称yourfix
。由于新提交M
记得刚刚yourfix
中存储 的哈希ID,Git仍然拥有该提交中 的所有文件,如果你想要它,准备提取。
并且,由于M
会将相同的提交哈希ID记为origin/theirfix
,因此现在可以安全地git push
提交{{1在M
向Git结束,并要求origin
更改自己的origin
(您的Git正在调用theirfix
)以指向origin/theirfix
,因为M
也记得他们以前的提交。当您运行M
时,Git将此称为快进操作 - 但请让其留下该术语以解决其他问题。