6

I found a peculiar behavior with git, and I can reproduce it every time on my machine.

If I have two local repositories, one bare inside the folder express.git, and the other non-bare with a working tree inside the folder express, both in the same parent folder, I can do the command git pull ../express.git from inside the express folder. This automatically updates everything inside express.

However, if I run the command git --git-dir /home/cisw470p/stu006/express/.git pull /home/cisw470p/stu006/express.git master from a location no located in either git repository, then the express repo will pull changes, but won't automatically update the working tree. I then have to run git add . to add all changes and then make another commit from inside express and now everything is good.

Why doesn't the long version of the command using the --git-dir option not automatically update the working tree for express? Is there a reason for this, or did I find a bug?

EDIT: I just tried it again but edited a different file and now it worked. I'm completely lost.

8
  • How are you expecting git to find the work tree with the long form? Have you tried adding the --work-tree=... arg? Commented Mar 16, 2012 at 22:08
  • Inside express is the work tree along with the .git folder, like a normal repo. Commented Mar 16, 2012 at 22:19
  • When giving git an explicit git-dir, why are you expecting it to just assume the parent of the git dir is a work tree? That could be a rather dangerous assumption in many cases (notably, if the git dir is actually a bare repo) Commented Mar 16, 2012 at 22:26
  • Good point. I'm still getting familiar with git. So far I've only encountered bare repos or repos where the working tree is in the parent of the .git folder so I thought it was like a default. Let me see if the work-tree option fixes everything. Commented Mar 16, 2012 at 23:14
  • Most people never even use the --git-dir or --work-tree flags. They're mostly only useful when writing esoteric scripts that need to reach in and poke at other repositories. When using these sorts of options, you need to specify everything because you're explicitly telling git not to follow its default heuristics to detect them. Commented Mar 16, 2012 at 23:33

1 Answer 1

12

If you run git --git-dir=some/dir/.git pull, by default git will assume the current directory is the work tree. Not the parent of some/dir/.git, but your current pwd. This means that running that command will try to update the current directory as if it's the work tree and will end up writing files into your pwd that don't belong there.

The appropriate solution is to use the --work-tree flag in conjunction with --git-dir to tell it where the work tree is. In this case you'd want git --git-dir=some/dir/.git --work-tree=some/dir pull. However, after experimentation it seems there's a second problem here. If you try this command as-is, you'll probably be told git-pull cannot be used without a working tree. It seems the issue here is git needs its work tree to be an absolute path instead of a relative one.

What you really want to run is git --git-dir=some/dir/.git --work-tree="$PWD"/some/dir pull. Alternatively, you could just try cd some/dir && git pull. If you don't want to change your cwd, you can wrap this in a subshell, i.e. ( cd some/dir && git pull ).

Sign up to request clarification or add additional context in comments.

9 Comments

Interesting. Using a subshell works at the command line, but the problem is if i do (cd some/dir/.git && git pull) inside a hook script it won't work and I will get an error telling me no git repo exists at that location (fatal: Not a git repository); the same error whether I cd to the absolute paths /some/repo or /some/repo/.git. That's why I resorted to using --git-dir, and now --work-tree. However, I'm using absolute paths, and i'm is still getting the git-pull cannot be used without a working tree error. My path starts with /, which means it is absolute, right?
Yes, starting with a / means it's absolute. Maybe the path is wrong? Also, you should just use (cd some/dir && git pull), not (cd some/dir/.git && git pull). If you can run git pull from that dir in an interactive terminal, you should be able to do so from a subshell in a script.
Regardless, with or without the .git in the path I get the same error... I'll post it when I'm back from mobile. And yeah, I triple checked I'm typing the correct path.
@trusktr: Do you have the GIT_DIR or GIT_WORK_TREE environment variables set? The --git-dir and --work-tree arguments should be overriding those though.
Ahah, turns out it's a bug with the version of git that I have: stackoverflow.com/questions/9745941
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.