为什么`git checkout `阶段变化?

问题描述 投票:9回答:2

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

这是什么原因?这只是为了与git mv等其他命令保持一致,您期望进行更改吗?使用git checkout解决合并冲突时是否方便?还是有其他理由吗?

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

git branch git-branch git-checkout
2个回答
6
投票

它实际上是Git作者选择透露的实现细节。

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

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

请注意,有时,索引在冲突合并期间用作帮助区域。在这种情况下,对于某些文件F,最多有三个条目,在编号的槽1(基础),2(--ours)和3(--theirs)中,而不是正常槽零中的一个条目。如果是这样,您可以将三个索引槽条目中的任何一个提取到工作树,而不会干扰索引。但是如果你使用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命令。)


0
投票

简答

  1. git checkout总是将项目从索引中复制到工作树中。
  2. 如果您指定的提交不是您所在的提交(例如另一个分支的HEAD),则checkout将始终首先将该提交中的项目复制到索引中。
  3. 索引中与HEAD不同的任何内容都将显示为“分阶段更改”。这是定义。

另见Git checkout file from branch without changing index

© www.soinside.com 2019 - 2024. All rights reserved.