質問

This is kind of a weird one, and I apologize in advance if it doesn't have much application outside of my specific circumstances. I am using git to manage my deployment packages by committing and tagging a set of generated files relating to the deployment and a submodule which points to the release code. I am attempting to do a git checkout of this deployment tag from a bare repo on each machine into a different, empty directory. The output I get indicates that it has deleted the files it should have created, and the work-tree directory remains empty afterward.

$ ls -al /var/www/test/
total 0

$ git --bare --work-tree=/var/www/test/ checkout my_tag
D   .gitmodules
D   generated.tgz
D   release
D   signatures.md5
HEAD is now at 8946ff5... Generated contents of deployment package.

$ ls -al /var/www/test/
total 0

I should state that both the commit referenced by my_tag and the tip of master have the same 4 files (though with different contents). Which makes it all the stranger that the following procedure gets me 75% of the way there:

$ git --bare --work-tree=/var/www/test/ checkout master
D   .gitmodules
Previous HEAD position was 8946ff5... Generated contents of deployment package.
Switched to branch 'master'

$ ls -al /var/www/test/
total 4
-rw-r--r-- 1 root root    0 Oct 17 17:00 generated.tgz
drwxr-xr-x 2 root root 4096 Oct 17 17:00 release
-rw-r--r-- 1 root root    0 Oct 17 17:00 signatures.md5

$ git --bare --work-tree=/var/www/test/ checkout my_tag
D   .gitmodules
(---- git's warning about detached HEAD state cut ----)
HEAD is now at 8946ff5... Generated contents of deployment package

$ ls -al /var/www/test/
total 4624
-rw-r--r-- 1 root root 2103765 Oct 17 17:02 generated.tgz
drwxr-xr-x 2 root root    4096 Oct 17 17:00 release
-rw-r--r-- 1 root root 2614883 Oct 17 17:02 signatures.md5

The thing is, "release" is a git submodule, and I can't init or update it without .gitmodules, so 75% of the way there still isn't good enough.

One solution to this problem would be to simply clone the repo anew every time I deploy, and maybe I'll go that way if nobody can suggest a better solution. But ideally I'd like to keep one bare repo on each machine and checkout from that to a new work-tree each time. Can anybody tell me what's going on here?

For reference, I'm using Git 1.8.2.1.

役に立ちましたか?

解決

The basic problem is that checkout is comparing the desired revision (my_tag, master) against what's in HEAD in the --bare repo. (And the --bare argument is doing nothing.) So with my_tag, it says you're already in detached HEAD mode and on the desired rev—i.e., it should not change HEAD—and looks into the target directory, /var/www/test/, and sees that the files have been removed and gives you the D status for each. It assumes they were there because of the index (see below).

When you switch to checkout master, it figures: OK, you're moving from this detached-HEAD to master, it updates HEAD and checks out the changed files. But .gitmodules is the same in my_tag and head, so that one remains Deleted.

If you use checkout -f, it will assume it should replace the missing files.

Git also has the bad habit :-) of using $GIT_DIR/index to record what it is doing with the checkout, as well as $GIT_DIR/HEAD. This leads to left-behind files when files are removed from the thing you're trying to deploy. If the target directory is emptied out before doing a checkout -f that should be OK though. (Alternatively, set GIT_INDEX_FILE in the environment, naming a file you keep along with each unique deployment. I have not experimented with this but it should work well.)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top