I have a bare git repository setup for user fred
:
/home/fred/foo.git
I have set the group of every file in foo.git
to bar
:
$ chown -R fred:bar /home/fred/foo.git
(Note that fred
is not a member of group bar
)
And I have set the setgid
bit on for every directory in foo.git
:
$ find foo.git -type d -print0 | xargs -0 chmod g+s
However when fred
commits to the git repository, the group is not preserved in some files.
Specifically in the objects
directory I see:
foo.git/objects:
drwxrws--- 46 fred bar 4096 Apr 7 23:43 .
drwxrws--- 7 fred bar 4096 Apr 6 17:12 ..
drwxrws--- 2 fred bar 4096 Apr 6 17:11 07
drwxrws--- 2 fred bar 4096 Apr 6 17:11 10
drwxrwx--- 2 fred bar 4096 Apr 7 22:14 14 <--- HERE
drwxrws--- 2 fred bar 4096 Apr 6 17:11 17
^--- HERE
Notice that in objects/14
the setgid
bit is not set. So consequently when a new object is added to that directory:
foo.git/objects/14:
drwxrwx--- 2 fred bar 4096 Apr 7 22:14 .
drwxrws--- 46 fred bar 4096 Apr 7 23:43 ..
-r--r----- 1 fred fred 2595 Apr 7 22:14 95482f8..9d6bfe21
So now the 95482..
file doesn't have group bar
, it has group fred
.
I suspect that when fred
commited, git created a new directory on-demand called objects/14
to hold a new object, when it did this for some unknown reason the setgid
bit on the new 14
directory was not set, even though its parent directory objects
has the setgid
bit set.
If I try to reproduce this manually:
$ su fred # as user fred
$ mkdir test1 # create test1 dir
$ sudo chgrp bar test1 # set group to bar
$ sudo chmod g+s test1 # set setgid bit
$ ls -l
drwxrwsr-x 2 fred bar 4096 Apr 8 21:33 test1
$ mkdir test1/test2 # create dir test1/test2
$ ls -l
drwxrwsr-x 2 fred bar 4096 Apr 8 21:35 test2
^--- HERE
Notice the setgid
bit in the new test1/test2
is preserved, so when I...
$ touch test1/test2/test3
The new file is still group bar
as expected:
$ ls -l test1/test2
-rw-rw-r-- 1 fred bar 0 Apr 8 21:36 test3
Why doesn't git
seem to preserve the setgid
bit when it creates new directories in the .git
directory?
Is there some git setting I can make to fix this? Or can you explain what is causing this?
It turns out that when you specify the
core.sharedrepository
config, git doeschmod()
s on the files it creates. That way, the result is correct despite filesystem types and mount options, except in your one case where the repository owner isn't a member of the group it's shared with.That bad result happens because git's
chmod()
appears to succeed -- you can see it in an strace -- but ignores anything the issuing user isn't authorized to ask for.So to avoid that weirdity, the thing to do is
(or not specify --shared at all on the init) so git doesn't touch the filesystem's default permissions at all. Amusingly enough that makes everything work: