Git 如何在内部恢复索引和工作目录(在 reset/checkout 上)?
How does Git restore index and wokring directory internally (upon reset/checkout)?
我明白当我 checkout
或 reset --hard
到特定的 commit/branch 时,我会在我的工作目录和索引文件中获得相关内容。
但是 Git 如何在 checkout
或 reset --hard
上内部重建索引和工作目录内容。
索引恢复是通过读取我们checked-out/reset到的提交指向的树来完成的吗?
工作目录也是这样恢复的吗?
这是否意味着在 reset --hard
或 checkout <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 设置索引以匹配提交,索引将匹配提交。
我明白当我 checkout
或 reset --hard
到特定的 commit/branch 时,我会在我的工作目录和索引文件中获得相关内容。
但是 Git 如何在 checkout
或 reset --hard
上内部重建索引和工作目录内容。
索引恢复是通过读取我们checked-out/reset到的提交指向的树来完成的吗?
工作目录也是这样恢复的吗?
这是否意味着在 reset --hard
或 checkout <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 设置索引以匹配提交,索引将匹配提交。