为什么`git checkout <branch> <file>`进行更改?

时间:2017-05-24 15:58:06

标签: git branch git-branch git-checkout

如果我从一个干净的工作树开始并运行git checkout <branch> <file><branch>有这个文件的不同版本,我最终会进行分阶段而不是非分阶段的更改。

这是什么原因?这是为了与git mv之类的其他命令保持一致吗?使用git checkout解决合并冲突时是否方便?还是有其他理由吗?

这对我来说似乎有点奇怪,因为仅使用git checkout <branch> <file>并未提供任何关于我是否计划提交更改的指示。

2 个答案:

答案 0 :(得分:6)

这是Git作者选择透露的实现细节。

Git不能 - 或者更确切地说,可以直接从存储库中将文件读取到工作树中。它已经(或曾经)通过中介首先传递它们:它必须复制它们,或者至少在其他地方复制它们的重要统计数据 1 。只有这样,Git才能将数据复制到工作树文件中。 2 &#34;其他地方&#34;是索引条目。该索引也称为临时区域。

当你git checkout整个提交时,无论如何这都是你想要的。因此,首先复制到索引然后再复制到工作树的内部限制实际上是一个加分。因此,这种首先复制到索引中,然后再导入工作树的机制被嵌入到实现中。然后,最终,面向用户的git checkout前端获得了检出一个单独文件或一小部分文件的能力......并且它继续这样做通过索引。实现细节成为记录的功能。

请注意,有时,索引在冲突合并期间用作帮助区域。在这种情况下,对于某些文件 F ,最多有三个条目,编号为slot 1(base),2(--ours)和3( --theirs),而不是正常slot-zero中的一个条目。如果是这样,您可以将三个索引槽条目中的任何一个提取到工作树,而不会干扰索引。但是如果你使用git checkout从其他一些提交或树中提取文件,Git会将文件复制到索引中,并将其写入插槽零。这有删除更高编号的插槽的副作用,解决了合并冲突!

1 主要的是哈希ID。作为ElpieKay noted in a comment,Git必须将提交哈希解析为树形哈希,然后搜索各种树以找到感兴趣的文件,以便它可以获得blob哈希。索引条目本身也包含更多数据,包括工作树文件的stat结构数据,以使Git快速运行。

2 您仍然可以使用此工作流,使用git read-tree将树复制到索引中,然后使用git checkout-index将索引复制到工作中 - 树。最初,Git由一些shell脚本组成,例如git-checkout包裹着一些基本的C编码片段,如git-read-tree。 (这些名称都是这样的连字符,并且没有前端git命令。)

答案 1 :(得分:0)

简短答案

  1. git checkout 总是将项目从索引中复制到工作树中。

  2. 如果您指定的提交不同于您所在的提交(例如,另一个分支的HEAD),结帐将始终首先将提交中的项目复制到索引中。 / p>

  3. 索引中与HEAD不同的任何内容都将显示为“分阶段更改”。这是根据定义。

另请参阅Git checkout file from branch without changing index