Subdirectories in checked out directory of a previous revision not disappearing in Git?
I'm trying to use git checkout <hash> <directory>
to checkout a previous revision of a directory in my repo. This works to restore the files in the directory to their previous state, the only problem is that subdirectories that were added since the revision I checked out don't disappear.
For example, if my direc开发者_如何转开发tory structure were the following:
HEAD:
thing/dir1/
thing/dir2/
HEAD^:
thing/dir1/
If I do git checkout <hash>
, then I go into detached HEAD mode and everything matches fine. If instead I do git checkout <hash> thing/
, the contents of thing/dir1/
will revert, but thing/dir2/
will stay put.
Running git status
shows the file modifications from thing/dir1/
, but doesn't mention thing/dir2/
. This is weird, because in the context of HEAD^, thing/dir2/
shouldn't exist and should therefore be gone. git clean
doesn't help because it doesn't even show up as untracked.
Is there a way to checkout a previous revision of a directory which perfectly matches, without having to checkout the entire working tree?
UPDATE:
Looks like this will work:
git reset <hash> thing/
git checkout <hash> thing/
git clean -fd thing/
This leaves my working tree and index in a strange state, but has the desired effect.
From http://git-scm.com/docs/git-checkout:
Updates files in the working tree to match the version in the index or the specified tree. If no paths are given, git checkout will also update HEAD to set the specified branch as the current branch.
Further below it also says:
When < paths > or --patch are given, git checkout does not switch branches. It updates the named paths in the working tree from the index file or from a named (most often a commit). In this case, the -b and --track options are meaningless and giving either of them results in an error. The argument can be used to specify a specific tree-ish (i.e. commit, tag or tree) to update the index for the given paths before updating the working tree.
In other words, since you are not switching branches, the working directory will not reflect any changes to the HEAD pointer, but will show files that belong to the tree-ish, in this case it's HEAD^
The reason why thing/dir2 is still left on disc is that it still belongs to current HEAD (remember, HEAD is not moved) and there is no information in the tree-ish whats missing from the three-ish (in this case thing/dir2). So in effect you have thing/dir1 checked out to reflect the state of the HEAD^ hash and also thing/dir2 on disc since it belongs to HEAD.
As you already mention git checkout <hash>
makes git go into detached head mode. When checking out particular files really only the files are copied into your working directory and everything else is untouched.
Thus the files in thing/dir2/
don't show up in git status
because they are in the current state of HEAD
while thing/dir1
will show modified files.
If you really want to have the whole thing/
folder like in the last revision why not just delete it before?
rm thing/
git checkout <hash> thing/
I am not sure if it matches your needs. Use with caution! (Although when having no local uncommited changes everything should be restoreable.)
精彩评论