3

我正在尝试git checkout <hash> <directory>在我的存储库中签出目录的先前版本。这可以将目录中的文件恢复到以前的状态,唯一的问题是自检出修订后添加的子目录不会消失。

例如,如果我的目录结构如下:

HEAD:
thing/dir1/
thing/dir2/

HEAD^:
thing/dir1/

如果我这样做git checkout <hash>了,那么我会进入分离的 HEAD 模式,一切都匹配得很好。相反,如果我这样做git checkout <hash> thing/,内容thing/dir1/将恢复,但thing/dir2/会保持不变。

运行git status显示来自 的文件修改thing/dir1/,但未提及thing/dir2/. 这很奇怪,因为在 HEAD^ 的上下文中,thing/dir2/不应该存在,因此应该消失。 git clean没有帮助,因为它甚至没有显示为未跟踪。

有没有办法签出完美匹配的目录的先前版本,而无需签出整个工作树?

更新:

看起来这会起作用:

git reset <hash> thing/
git checkout <hash> thing/
git clean -fd thing/

这使我的工作树和索引处于奇怪的状态,但具有预期的效果。

4

2 回答 2

1

正如您已经提到git checkout <hash>的,使 git 进入分离头模式。在签出特定文件时,实际上只有文件被复制到您的工作目录中,其他所有内容都保持不变。

因此,文件thing/dir2/不会显示在其中,git status因为它们处于当前状态,HEADthing/dir1将显示修改后的文件。

如果您真的想要thing/像上一个修订版那样拥有整个文件夹,为什么不先将其删除?

rm thing/
git checkout <hash> thing/

我不确定它是否符合您的需求。谨慎使用!(尽管当没有本地未提交的更改时,一切都应该是可恢复的。)

于 2011-05-02T17:10:16.400 回答
1

来自http://git-scm.com/docs/git-checkout

更新工作树中的文件以匹配索引或指定树中的版本。如果没有给出路径,git checkout 也会更新 HEAD 以将指定的分支设置为当前分支。

下面还说:

当 <paths> 或 --patch 给出时, git checkout不会切换分支。它从索引文件或命名(通常是提交)更新工作树中的命名路径。在这种情况下, -b 和 --track 选项没有意义,并且给它们中的任何一个都会导致错误。该参数可用于指定特定的树(即提交、标记或树)以在更新工作树之前更新给定路径的索引。

换句话说,由于您没有切换分支,因此工作目录不会反映对 HEAD 指针的任何更改,但会显示属于树状的文件,在这种情况下是 HEAD^

thing/dir2 仍然留在磁盘上的原因是它仍然属于当前的 HEAD(请记住,HEAD 没有移动)并且树状结构中没有信息从三个 ish 中丢失了什么(在这种情况下是 thing/目录 2)。因此,实际上您检查了 thing/dir1 以反映 HEAD^ 哈希的状态以及磁盘上的 thing/dir2,因为它属于 HEAD。

于 2011-05-02T17:18:11.990 回答