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 directory 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:
Further below it also says:
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.