Git 如何在内部恢复索引和工作目录(在 reset/checkout 上)?

How does Git restore index and wokring directory internally (upon reset/checkout)?

我明白当我 checkoutreset --hard 到特定的 commit/branch 时,我会在我的工作目录和索引文件中获得相关内容。

但是 Git 如何在 checkoutreset --hard 上内部重建索引和工作目录内容。

索引恢复是通过读取我们checked-out/reset到的提交指向的树来完成的吗?

工作目录也是这样恢复的吗?

这是否意味着在 reset --hardcheckout <some_branch> 之后,索引和工作目录将 总是 匹配该提交的树,因为它们是从它重建的?


编辑:我主要想问的是:index/WD 内容的恢复是使用我们到达的提交指向的树完成的吗?因为在我看来,git 除了从提交历史记录

中获取内容外,没有其他方法可以获取该内容

这是否意味着在 reset --hard 或 checkout 之后,索引和工作目录将始终与该提交的树匹配,因为它们是从中重建的?

简短回答:是

长答案:

git checkout:

Updates files in the working tree to match the version in the index or the specified tree.

https://git-scm.com/docs/git-checkout

git-reset --hard:

Resets the index and working tree. Any changes to tracked files in the working tree since are discarded.

https://git-scm.com/docs/git-reset

这两个命令都移动 HEAD,然后检查它被移动到的任何提交,并相应地更改索引 and/or WD。如果它不改变一个或两个,它仍然充当文件状态的管理员 在提交时 并允许你 运行 命令进行比较您的 WD 和当时文件状态的索引。

希望对您有所帮助,我不确定您的问题到底是什么。

不完全是。至少,不是工作目录。

老实说,我花了几分钟才弄明白你的问题可能是什么意思。您在询问工作目录是否会在 运行 之后与签出的提交匹配,您说您知道的命令将工作目录设置为与签出的提交匹配,所以问题是......一个有点模糊。

但是在 ARE 情况下,工作目录最终会与检出提交中的内容不同。例如,被忽略(或未跟踪)的文件通常不会受到干扰。在某些情况下这是不可能的;也许我有一个名为 foo 的未跟踪文件,但目标树在同一路径下也有一个名为 foo 的文件。不同的命令处理方式不同。 (这里需要注意的是,checkout commit 是一个 非常 checkout commit -- path 不同的命令。)一些命令会破坏您的本地未跟踪数据(然后将无法恢复,至少就任何 git 机制而言),而其他机制将中止并警告您本地更改将被覆盖。

因此,说工作树是来自目标树的 "rebuilt" 严格来说是不正确的 - 因为目录并非完全 rm 然后从树数据中重新创建。而是根据需要添加、删除或替换文件(无论如何这是一个更有效的过程)。

对于索引:很难显示 "symptom" 的索引没有完全重建,因为索引中没有与未跟踪文件类似的概念。我希望 git 能够利用它为所有内容存储的哈希值,这样它只会再次更改需要更改的内容,而不是完全重建;但在这种情况下我不是 100% 确定,这是一个并不重要的实现细节。如果您告诉 git 设置索引以匹配提交,索引将匹配提交。