如何与一台机器上的多个用户共享Git存储库?


216

我在登台服务器上有一个Git存储库,需要多个开发人员才能将其存储到。git-init似乎有一个非常接近我要寻找的标志:--shared,除了我也希望多人同时访问该存储库。的git-clone--shared标志做完全不同的事情。

更改现有存储库权限的最简单方法是什么?


我使用“Github上的Windows”和两个Github上之间切换帐户: stackoverflow.com/questions/18565876/...
艾丽莎

Answers:


186

许可是一种害虫。

基本上,您需要确保所有这些开发人员都可以写入git repo中的所有内容。

跳至“新波解决方案”以获取授予一组开发人员写功能的高级方法。

标准解决方案

如果将所有开发人员放在一个专门创建的小组中,原则上可以做到:

chgrp -R <whatever group> gitrepo
chmod -R g+swX gitrepo

然后umask将用户的更改为002,以便使用组可写权限创建新文件。

问题在于大军。如果您所使用的发行版采用umask022(例如users,默认情况下每个人都有一个公共组),那么这可能会在其他地方引发安全问题。迟早会有一些事情搞砸您精心设计的权限方案,使存储库不起作用,直到您可以root访问并对其进行修复(即,重新运行以上命令)。

新波解决方案

上乘的解决方案(虽然尚不为人所理解,并且需要更多的OS /工具支持)是使用POSIX扩展属性。我只是最近才来这方面的,所以我在这里的知识并不那么热。但基本上,扩展的ACL可以在3个以上默认插槽(用户/组/其他)上设置权限。

因此,再次创建您的组,然后运行:

setfacl -R -m g:<whatever group>:rwX gitrepo
find gitrepo -type d | xargs setfacl -R -m d:g:<whatever group>:rwX

这将为组设置扩展的ACL,以便组成员可以读取/写入/访问已经存在的任何文件(第一行);然后,还告诉所有现有目录新文件应应用相同的ACL(第二行)。

希望能带您上路。


62
git init有一个名为--shared的参数,该参数为组工作设置core.sharedRepository变量。您还可以在现有存储库上设置变量。这消除了手动设置umask的需要,因为git会在处理文件之前将其设置为合理的值。
ptman 2010年

6
+1代表POSIX扩展属性-给我个消息!
RobM 2011年

5
当我这样做时chmod -R g+swX,它使Git非常不高兴,并决定它不再是git存储库(“ repo似乎不是git存储库”)。我不得不修改所有文件。要仅在目录上设置setgid位,请尝试find /path/to/repo -type d -print0 | xargs -0 chmod g+s。仍然做chgrp -R thegroup /path/to/repo
rescdsk 2012年

10
chmod -R g+swX gitrepo将setguid位应用于文件,这是安全隐患。相反,您可以用来find . -type d -exec chmod g+s {} +仅将其应用于目录。
伊恩·邓恩

1
ACL(setfacl)没有设置setgid来强制执行在目录中创建的新文件和子目录以继承其组ID。因此,必须通过chmod分别设置setgid。但是,Git的--shared选项(git-scm.com/docs/git-init)允许您设置并覆盖用户的umask。
Chase T.

121

如果您使用以下命令创建了存储库(或从现有存储库中克隆了一个新的裸存储库)

$ git init --shared=group 

要么

$ git init --shared=0NNN

Git应该能够处理超出默认umask所提供权限之外的权限。最后,在我的Git版本(1.6.3)中,这是正确的。当然,这假定您的用户在同一组中。

但是,如果我需要以不同程度的读/写来管理多个组中的用户,那么我会使用gitosis。我也听说过有人提到过gitolite(http://github.com/sitaramc/gitolite),这是一个可以提供分支级别权限的gitosis分支,但不能说我每个人都亲自使用过它。


9
这绝对是正确的答案。
ELLIOTTCABLE

4
我遇到了这个问题,这是迄今为止最好的答案。唯一的问题是该--shared参数采用八进制而不是十六进制。我已经在Git 1.7.8的源代码中确认了这一点,第二个示例应该是git init --shared=0NNN
qpingu 2012年

3
什么是— NNN权限掩码或组号或其他内容?
Craig McQueen 2014年

20
顺便说一句,上面的“组”是一个关键字,而不是您的组名的占位符。您可以使用chgrp命令分配组。对于新的存储库,这里是git init --bare --shared=group myprojmyproj是您的存储库名称,然后是chgrp -R mygroup myprojmygroup是您的组名称。
labradort 2014年

2
请注意,如果您的用户在其默认组与应有的默认组不同时进行提交,则可能会搞砸。要解决此问题,您需要每个用户将自己在存储库中拥有的每个文件更改为正确的组。除非您弄清楚如何在提交和推送之前让所有人在正确的组下/将新文件创建/切换到正确的组,否则这种情况将再次发生。
ragerdl '16

55

这还没有说,所以我想快速添加它。

为了确保权限问题不会变得丑陋,请确保在git共享存储库的配置文件中设置以下内容:

[core]
    sharedRepository = true

这将确保遵守系统的“ umask”设置。


6
根据git-config(1)(kernel.org/pub/software/scm/git/docs/git-config.html)core.sharedRepository,您需要将其设置为“ umask”或“ false”以具有git的尊重用户的umask。
大卫·史密特

14
这和user35117的答案是正确的。请注意,“ true”与“ group”相同,可以使用命令来设置git config core.sharedRepository true
ColinM

当文件被推送到远程位置时,它是否仍会更改文件的所有权?

2
如果你想克隆时,而不是在事后对此进行设置,相当于git init --sharedgit clone --config core.sharedRepository=true。git奇怪,--shared在类似的命令中用于不同的含义。
stevek_mcc

21

Git用户手册》介绍了如何以几种方式共享存储库

尽管功能齐全,但是共享存储库的方法更为复杂:

我们将GitHub用于由6个开发人员组成的团队。


1
我喜欢胃病。这是一种基于公共密钥控制访问的非常有效的方法。
Mike Mazur

这些解决方案中的任何一个如何解决“我希望多个人拉到该存储库”的问题?
womble

看一下gitosis。那解决了你的问题。
pilif

3
当您共享存储库时,人们将能够从中提取信息。他们可能需要克隆它,或添加一个远程分支。我链接的文档将非常清楚地引导您解决问题。我已使用上述所有方法来帮助开发人员与Git协作源代码。据我所知ServerFault不是手持的。
jtimberman

3
我必须同意使用Gitosis。通过使用由多个SSH密钥验证的单个帐户,可以解决权限问题。也可以通过git commits对其进行完全管理。
杰里米·布斯

9

还可以查看用于托管git存储库的gitolite。Gitosis显然不再被开发。


4

修复共享存储库中的权限(使用户在推送时不会出现权限问题)的一种方法是创建一个更新后的钩子脚本即可。这应该可以在任何git版本中使用。

假设您在/myrepo.git中有一个共享存储库。该存储库中的所有文件都属于mysharedgroup。推送到该存储库的所有用户也应属于mysharedgroup。现在创建以下文件(将mysharedgroup更改为您的首选项):

/myrepo.git/hooks/post-update

#!/bin/sh
chmod -R g+w . 2>/dev/null
chgrp -R mysharedgroup . 2>/dev/null

当用户具有不同的默认组时的正确答案
Pat

在目录上设置setgid位将导致用户创建的文件继承与目录相同的组所有权(如果用户属于该组)。即使它不是用户的默认组。然后,不需要此钩子。这就是@womble的答案(以及我对此的评论)。
rescdsk 2012年

在我的centos7机器上,尝试了此页上列出的每个解决方案后,上述@bkmks解决方案的变体是唯一有效的选项(设置合并后和检出后挂钩,而不是如上所述的更新后)。
Mike Godin

我认为,推广将STDER上的错误消息或警告传递到的解决方案是不好的建议/dev/null。请先让用户看到这些消息,然后再自行决定。
DanielBöhmer18年

3

要汇总其他各种关于建立新仓库的答案和评论中的一些好建议,请执行以下操作:

如果你正在建立一个全新的回购myrepo/srv/git该组mygroup,这是你想要什么:

mkdir /srv/git/myrepo.git
chgrp mygroup /srv/git/myrepo.git
git init --bare --shared /srv/git/myrepo.git
  1. 第一行创建仓库目录
  2. 第二行将其组设置为 mygroup
  3. 第三行使用以下配置初始化裸仓库:
    1. core.bare = true:使其成为裸露的仓库
    2. core.sharedrepository = 1(与相同core.sharedrepository = group):repo目录以及以后在其中创建的所有目录将由git管理,以允许mygroup读取,写入和执行权限(同时设置了sgid位-以便与mygroup不是其用户的用户一起工作初级组)
    3. receive.denyNonFastforwards = 1:拒绝非快速推送到仓库

如果要微调的用户,组或其他用户的权限,使用--shared=0NNN,这里NNN是标准的用户,组和其他位文件(在执行和SGID位目录将通过适当的git管理)。例如,这允许对用户的读取和写入访问权限,以及对组的只读访问权限(对其他用户没有访问权限):

git init --bare --shared=0640 /srv/git/myrepo.git

这样就可以对用户和组进行读写访问(而不能访问其他用户):

git init --bare --shared=0660 /srv/git/myrepo.git

这允许对用户和组的读写访问,以及对其他用户的只读访问:

git init --bare --shared=0664 /srv/git/myrepo.git

请注意,如果您不想允许对该组进行写访问,请确保首先使用chown来设置存储库的所有者,然后git init以该用户身份运行命令(以确保使用正确的所有者初始化存储库。所有初始文件和子目录)。


比更高的投票答复更正确。
XO01


1

对于现有的存储库,这样做对我来说确实有效。这需要从以下几个答案和评论中获取建议:

在服务器的存储库父目录中:

chgrp -R <whatever group> gitrepo
chmod -R g+wX gitrepo
cd gitrepo
find . -type d -exec chmod g+s {} +
git config core.sharedRepository group

0

@stevek_mcc答案是我在Google搜索此问题时一直在寻找的答案

git clone --config core.sharedRepository=true
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.