6

We'd like to use git to maintain system configurations. Because sometimes configuration data exists outside of /etc, we've started doing something like this on our systems:

  # cd /
  # git init
  # git add etc
  # git add some/other/path
  # git commit -m 'initial import'

And so forth. This works, up to a point. As long as your cwd == '/', git behaves normally. However, if you try, for example, to run git from inside a subdirectory:

cd /etc
git status

You get garbage. In our case, thousands of lines of "deleted:" listings for files that clearly still exist. This behavior appears to be exclusive to running git in /; doing the same thing anywhere else works just fine.

I can "fix" the behavior like this:

GIT_WORK_TREE=/ git status

And hey, everything works the way Linus intended...but this is a pain. I don't want to set it in the environment unilaterally (because this would conflict with the use of git in other repositories), and I'd like to avoid a wrapper script. Do I have any other options?

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Note: Git 2.4.1+ will fix this (Q2 2015). See [my answer below](http://stackoverflow.com/a/30093777/6309). – VonC May 07 '15 at 06:49

3 Answers3

4

This is a complete guess that you could use to investigate further, but I suspect that git's "find the .git directory" behavior is interacting with the fact that / is its own parent directory. Maybe the "stop at the root" logic has a fencepost-type error.

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • Ah, git. Always a new surprise somewhere. I like your guess though. +1 – Norman Ramsey Dec 23 '09 at 02:31
  • This was also my guess (and why I suspect that setting GIT_WORK_TREE would fix it). I'm just wondering if there's a more graceful way of working around the behavior...a git config option? I see that there's a newer version of git out (we're running 1.63); perhaps I should see if that sill behaves the same way. – larsks Dec 23 '09 at 02:48
  • @NR: Hi there! I like git better than the alternatives. I think that they *all* have surprises (like Subversion's "Surprise! You can't actually use svndump/svnload if you've moved things around!"). – larsks Dec 23 '09 at 02:49
  • @larsks: sounds worthy of having a bug filed to me :) – hobbs Dec 23 '09 at 02:52
  • Alas, upgrading to the current release of git does not resolve this problem. – larsks Dec 23 '09 at 03:09
3

Setting the core.worktree option on the repository takes care of this nicely:

git config core.worktree /

This works much better than setting GIT_WORK_TREE in the environment. Yay!

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Also, thanks http://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked – larsks Dec 23 '09 at 03:27
0

This will be fixed in Git 2.4.1+ (Q2 2015).
See commit 84ccad8 by Jeff King (peff), and merged in 7502b23.

init: don't set core.worktree when initializing /.git

If you create a git repository in the root directory with "git init /", we erroneously write a core.worktree entry.
This isn't wrong, in the sense that it's OK to set core.worktree when we don't need to. But it is unnecessarily surprising if you later move the .git directory to another path (which usually moves the relative working tree, but is foiled if there is an explicit worktree set).

The problem is that we check whether core.worktree is necessary by seeing if we can make the git_dir by concatenating "/.git" onto the working tree.
That would lead to "//.git" in this instance, but we actually have "/.git" (without the doubled slash).

(That is why core.worktree is incorrectly set here, when git init is done at the root folder /)

We can fix this by special-casing the root directory. I also split the logic out into its own function to make the conditional a bit more readable (and used skip_prefix, which I think makes it a little more obvious what is going on).

No tests, as we would need to be able to write to "/" to do so.
I did manually confirm that:

sudo git init /
cd /
git rev-parse --show-toplevel
git config core.worktree

still finds the top-level correctly (as "/"), and does not set any core.worktree variable.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250