如何在Git仓库中正确使用组文件权限?

33

我们使用文件路径访问共享的git存储库,为了某些原因我暂时不透露,使用了--shared=group 创建。

我们有各种unix组,但全部共享一个公共组。如果我在git存储库上运行chgrp -R,则每个人都可以从中读取,但如果某人经常写入它,则通常会创建新文件,这些文件不使用公共组。

这个问题似乎是由于我们的主要组不是共享组,如果我们运行newgrp,所有事情似乎都可以正常工作。

然而,这种方法存在问题:newgrp很慢并且会产生一个新shell,这使我认为在.bash_profile 中调用它是一个坏主意,甚至没有考虑我们是否想要所有 的新文件都使用公共组。仅依靠记忆在进行任何git工作之前运行它似乎也是灾难的配方。

那么... 有什么建议吗?


2
尝试使用 gitolite,您只需要一个 git 用户。 - takeshin
7
对我们来说,下载更多的软件并不是一个真正的选择。 - rich
5个回答

29

使用以下命令可以将未使用 --shared 创建的现有存储库变为共享状态:

# make the repository shared
git config core.sharedRepository group # or whatever other sharing option
# fix the setgid bit
find . -type d | xargs chmod g+s
# repair the permissions
chmod -R g+r *

2
在我的情况下,我不得不执行“chmod -R g+rw *”,因为组应该有写入权限而不仅仅是读取权限。否则,感谢您的回答。 - Denis V
感谢 @fikovnik,这帮助我在切换分支时使我的仓库对 www-data 用户可读而不丢失权限。除了您上面的答案之外,对我来说缺少的一部分是将自己添加到 www-data 组中 - 否则,目录会在我切换分支时丢失 setgid 位。 chmod 手册说明此行为取决于系统。在 Linux 上,chmod 系统调用的行为似乎是清除目录的 setgid 位,除非用户属于该组,并且似乎 git 使用 chmod 系统调用来应用 core.sharedRepository 设置。 - akwizgran
我还需要执行 chmod -R g+rw .*(注意有一个点),因为这个文件是 .git/FETCH_HEAD,其他组成员无法写入。 - TheChymera
请注意,chmod -R g+rw .* 命令也会影响以.开头的其他条目,特别是父目录..。这是一个相当大的意外副作用,最好明确指定.git而不是全部,例如chmod -R g+rw .git - Andrew Richards

24

你还需要对组设置 setgid 位

chgrp -R GROUP /path/to/repo
find /path/to/repo -type d -print0 | xargs -0 chmod g+s 

8
永远不要对一个git仓库执行chmod -R g+s命令,因为你所做的不仅仅是你以为的那样,而是在每个文件上启用了setgid。 - Arrowmaster
好吧,确实这不是最好的做法。幸运的是,它们中没有一个可执行文件。我已经更新了帖子,只会击中目录(这是必需的)。 - Wes Hardaker
2
如果你要使用find命令,最好使用-print0选项来保护自己免受那些在分支/标签名称中使用空格或其他奇怪字符的人的影响。 - Arrowmaster
1
这对我不起作用,在新创建的目录上,git由于某种原因没有设置setgid位:http://stackoverflow.com/questions/15889573/setgid-bit-not-preserved-by-git-on-new-directory-in-git-folder - Andrew Tomazos
1
如果父目录设置了setgid,则应该这样做。 - Wes Hardaker
4
查找 /path/to/repo 目录下的所有子目录,并为每个子目录设置组ID位。命令如下:find /path/to/repo -type d -exec chmod g+s {} ; - rich remer

12

这是一个裸仓库吗?如果是裸仓库并且在创建时使用了 --shared 选项,则不应该发生这种情况,这就是我问的原因。

如果这是一个裸仓库,可能有一些目录被更改为 g-s,如果发生了这种情况,则需要仅对所有目录执行 chmod g+x,确保不对任何文件执行。比那更简单的方法可能是只需从某人的克隆中 git init --bare --shared=group 创建新仓库并将内容推回去。


8
一旦裸仓库设置了shared=group标志,git就会自动处理剩下的事情,所以以下操作只需要执行一次。此外,对于此用途,setgid已被弃用。下面是我从serverfault复制/粘贴的答案:
假设repogroup是您的组,并且您已经进入了存储库目录:
首先将共享标志更改为group:
git config core.sharedRepository group 

注意:这里必须使用关键字 group,而不是组名称。这相当于使用选项 --shared=group 创建裸仓库。然后更改整个仓库的组:
chgrp -R repogroup .

为了确保现有的目录具有组可写权限 (g+w),并且现有的可执行文件也变成了组可执行文件 (g+X),您还需要:
chmod -R g+wX .

一旦你完成了这个步骤,git 将会遵从 shared=group 标志,并在接下来的文件中处理组权限,无论是已存在或是新建的文件,因此你将不再需要使用 umaskchgrp 了。
如果我找到源代码,我会在评论中放上。

你说“setgid在这种情况下已经被弃用了”,能否提供一些背景或原因,这将非常有帮助,否则这只是道听途说而已。同时,你也没有提出setgid的替代方案。使用ACL(例如setfacl)可能是一种方法,但并不是所有文件系统都支持或启用ACL。 - Andrew Richards

5

我必须结合以上答案来使用:

git config core.sharedRepository group
chgrp -R GROUP /path/to/repo
find /path/to/repo -type d -exec chmod g+rwxs {} \;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接