Como compartilhar um repositório Git com vários usuários em uma máquina?

216

Eu tenho um repositório Git em um servidor intermediário para o qual vários desenvolvedores precisam ser capazes de acessar. git-initparece ter uma bandeira muito próxima do que estou procurando: --sharedexceto que eu gostaria que várias pessoas puxassem para esse repositório também. O git-clone's --sharedflag faz algo totalmente diferente.

Qual é a maneira mais fácil de alterar as permissões de um repositório existente?

Andrey Fedorov
fonte
Estou usando o "Github for Windows" e alterno entre duas contas do Github: stackoverflow.com/questions/18565876/…
Alisa

Respostas:

186

Permissões são uma praga.

Basicamente, você precisa garantir que todos esses desenvolvedores possam gravar em tudo no repositório git.

Vá para The New-Wave Solution para obter o método superior de conceder a um grupo de desenvolvedores a capacidade de gravação.

A solução padrão

Se você colocar todos os desenvolvedores em um grupo especialmente criado, poderá, em princípio, apenas:

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

Em seguida, altere umaskpara os usuários para 002que novos arquivos sejam criados com permissões graváveis ​​em grupo.

Os problemas com isso são legião; se você estiver em uma distribuição que assume uma parte umaskde 022(como ter um usersgrupo comum que inclua todos por padrão), isso pode abrir problemas de segurança em outro local. E mais cedo ou mais tarde, algo vai estragar seu esquema de permissões cuidadosamente criado, colocando o repositório fora de ação até você obter rootacesso e corrigi-lo (ou seja, reexecutar os comandos acima).

A solução New-Wave

Uma solução superior - embora menos compreendida e que exija um pouco mais de suporte do SO / ferramenta - é usar atributos estendidos do POSIX. Eu só vim para essa área recentemente, então meu conhecimento aqui não é tão quente quanto poderia ser. Mas, basicamente, uma ACL estendida é a capacidade de definir permissões em mais do que apenas os 3 slots padrão (usuário / grupo / outro).

Então, mais uma vez, crie seu grupo e execute:

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

Isso configura a ACL estendida para o grupo, para que os membros do grupo possam ler / gravar / acessar qualquer arquivo que já esteja lá (a primeira linha); informe também a todos os diretórios existentes que novos arquivos devem ter a mesma ACL aplicada (a segunda linha).

Espero que você esteja no seu caminho.

mulher
fonte
62
O git init possui um parâmetro chamado --shared, que configura a variável core.sharedRepository para o trabalho em grupo. Você também pode definir a variável em um repositório existente. Isso elimina a necessidade de definir manualmente o umask como git, configurando-o para um valor sensato antes de manipular arquivos.
ptman 17/02/10
6
+1 para atributos estendidos do POSIX - novidades para mim!
RobM
5
Quando eu fiz chmod -R g+swXisso, deixou o Git muito infeliz e decidiu que não era mais um repositório git ("repo não parece ser um repositório git"). Eu tive que chmod gs todos os arquivos . Para definir apenas o bit setgid nos diretórios , tente find /path/to/repo -type d -print0 | xargs -0 chmod g+s. Ainda faça o chgrp -R thegroup /path/to/repo.
rescdsk
10
chmod -R g+swX gitrepoaplicará o bit setguid aos arquivos, o que é um risco à segurança. Em vez disso, você pode find . -type d -exec chmod g+s {} +aplicá-lo apenas a diretórios.
22612 Ian
1
A ACL (setfacl) não tem configuração para setgid para impor novos arquivos e subdiretórios criados em um diretório para herdar seu ID de grupo. Portanto, você deve definir o setgid separadamente através do chmod. A opção --shared do Git ( git-scm.com/docs/git-init ), no entanto, permite que você configure o gid e substitua a umask do usuário.
perseguição T.
121

se você criou o repositório (ou clonou um novo repositório vazio de um existente) com

$ git init --shared=group 

ou

$ git init --shared=0NNN

O Git deve manipular permissões acima e além do que o umask padrão fornece. Finalmente, isso é verdade na minha versão do Git (1.6.3). Obviamente, isso pressupõe que seus usuários estão no mesmo grupo.

No entanto, se eu precisasse gerenciar usuários em vários grupos com diferentes graus de leitura / gravação, eu usaria gitosis. Também ouvi menção ao gitolite ( http://github.com/sitaramc/gitolite ), um garfo de gitose que deve fornecer permissões em nível de ramificação, mas não posso dizer que já o usei pessoalmente.

Beachhouse
fonte
9
Esta é definitivamente a resposta correta.
ELLIOTTCABLE
4
Eu tive esse problema e esta é de longe a melhor resposta. O único problema é que o --sharedargumento recebe um octal, não hexadecimal. Eu confirmei isso na fonte do Git 1.7.8 e o segundo exemplo deve ser git init --shared=0NNN.
qpingu
3
O que é NNN- máscara de permissão ou número de grupo ou outra coisa?
Craig McQueen
20
Aliás, "grupo" acima é uma palavra-chave, não um espaço reservado para o nome do seu grupo. Você atribui o grupo usando o comando chgrp. Para um novo git init --bare --shared=group myprojrepositório , é onde myproj é o nome do seu repositório, seguido de chgrp -R mygroup myprojonde mygroup é o nome do seu grupo.
Labradort
2
Aviso: se os usuários fizerem confirmações quando o grupo padrão for diferente do que deveria ser, ele poderá estragar tudo. Para corrigir esse problema, cada usuário precisará chgrp todos os arquivos que eles possuem no repositório para o grupo certo. Isso ocorrerá a menos que você decida como fazer com que todos criem / alternem novos arquivos no / para o grupo certo antes de confirmar e enviar.
precisa saber é o seguinte
55

Isso não foi dito, então eu quero adicioná-lo rapidamente.

Para garantir que os problemas de permissão não cortem sua cabeça feia, defina o seguinte no arquivo de configuração do seu repositório compartilhado git:

[core]
    sharedRepository = true

Isso garantirá que as configurações "umask" do seu sistema sejam respeitadas.

Niels Joubert
fonte
6
De acordo com git-config (1) ( kernel.org/pub/software/scm/git/docs/git-config.html ) core.sharedRepository, você precisa definir isso como "umask" ou "false" para ter respeito pelo git umask do usuário.
David Schmitt
14
Esta resposta e do user35117 estão corretas. Note-se que "verdadeiro" é o mesmo que "grupo", e isso pode ser definido com o comando git config core.sharedRepository true.
ColinM
Ele ainda altera a propriedade de um arquivo quando é enviado para remoto?
Duc Tran
2
Se você deseja configurar isso ao clonar e não após o fato, o equivalente a git init --sharedé git clone --config core.sharedRepository=true. Estranho de git usar --sharedpara significados tão diferentes em comandos semelhantes.
stevek_mcc
21

O Manual do Usuário do Git descreve como compartilhar um repositório de várias maneiras.

Mais complicadas, embora as maneiras completas de compartilhar repositórios sejam:

Usamos o GitHub para uma equipe de 6 desenvolvedores.

jtimberman
fonte
1
Eu gosto de Gitosis. É uma maneira bastante eficaz de controlar o acesso com base em chaves públicas.
Mike Mazur
Como alguma dessas soluções resolve o problema de "Gostaria que várias pessoas puxassem para esse repositório"?
Womble
dê uma olhada na gitosis. aquele resolve o seu problema.
pilif
3
Quando você compartilha o repositório, as pessoas poderão retirá-lo. Eles provavelmente precisarão cloná-lo ou adicionar uma ramificação remota. A documentação que vinculei o ajudará muito claramente a resolver seu problema; Eu usei todos os métodos descritos para ajudar os desenvolvedores a colaborar com o código-fonte com o Git. Que eu saiba ServerFault não é para segurar.
#
3
Eu tenho que concordar com o uso de Gitosis. Ele contorna o problema de permissões usando uma única conta autenticada por várias chaves SSH. Também é gerenciado inteiramente por meio de commits git.
Jeremy Bouse
9

Veja também o gitolite para hospedar seu repositório git. Aparentemente, a gitose não está mais sendo desenvolvida.

mt3
fonte
4

Uma maneira de corrigir permissões no repositório compartilhado, para que os usuários não tenham problemas de permissão ao enviar, é criar um script de gancho pós-atualização que faça exatamente isso. Isso deve funcionar em qualquer versão do git.

Suponha que você tenha um repositório compartilhado em /myrepo.git. Todos os arquivos desse repositório pertencem ao mysharedgroup . Todos os usuários que enviam para esse repositório também devem pertencer ao mysharedgroup . Agora crie o seguinte arquivo (alterando o mysharedgroup para suas preferências):

/myrepo.git/hooks/post-update

#!/bin/sh
chmod -R g+w . 2>/dev/null
chgrp -R mysharedgroup . 2>/dev/null
bkmks
fonte
a resposta certa para quando os usuários tiverem diferentes grupos padrão
Pat
Definir o bit setgid em um diretório fará com que os arquivos criados pelos usuários herdem a mesma propriedade do grupo que o diretório (se os usuários pertencerem a esse grupo). Mesmo que não seja o grupo padrão dos usuários. Então este gancho não é necessário. Isto é o que a resposta do @ womble (e meu comentário) faz.
rescdsk
Na minha máquina centos7, depois de tentar todas as soluções listadas nesta página, uma variante da solução do @ bkmks acima era a única opção que realmente funcionava (configurando os ganchos de pós-mesclagem e pós-checkout em vez de pós-atualização como acima).
9788 Mike Angin
Eu acho que é um mau conselho promover uma solução que canalize mensagens de erro ou avisos no STDER para /dev/null. Deixe o usuário ver essas mensagens primeiro e depois decidir por conta própria.
Daniel Böhmer
3

Para agregar os pequenos conselhos de várias outras respostas e comentários sobre a criação de um novo repositório:

Se você estiver configurando um novo repo marca myrepono /srv/gitpara o grupo mygroup, este é o que você quer:

mkdir /srv/git/myrepo.git
chgrp mygroup /srv/git/myrepo.git
git init --bare --shared /srv/git/myrepo.git
  1. a primeira linha cria o dir de repo
  2. a segunda linha define seu grupo para mygroup
  3. a terceira linha inicializa um repositório simples com a seguinte configuração:
    1. core.bare = true: torná-lo um repositório simples
    2. core.sharedrepository = 1(o mesmo que core.sharedrepository = group): o diretório repo e todos os diretórios criados posteriormente serão gerenciados pelo git para permitir permissões de mygroupleitura, gravação e execução (com o bit sgid definido também - para trabalhar com usuários para os quais mygroupnão é seu grupo primário)
    3. receive.denyNonFastforwards = 1: negar impulsos não rápidos para o repositório

Se você deseja ajustar as permissões de usuário, grupo ou de outros usuários, use --shared=0NNN, onde NNNestão o usuário, grupo e outros bits padrão para arquivos (os bits execute e sgid nos diretórios serão gerenciados adequadamente pelo git). Por exemplo, isso permite acesso de leitura e gravação ao usuário e acesso somente leitura ao grupo (e nenhum acesso a outro):

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

Isso permite acesso de leitura e gravação ao usuário e grupo (e nenhum acesso a outros):

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

Isso permite acesso de leitura e gravação ao usuário e grupo e acesso somente leitura a outros:

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

Observe que, se você não permitir o acesso de gravação ao grupo, use primeiro chownpara definir o proprietário do repositório e execute o git initcomando como esse usuário (para garantir que o repositório seja inicializado com o proprietário correto para todos os arquivos e subdiretórios iniciais).

Justin Ludwig
fonte
Mais correto do que as respostas de voto mais altas.
XO01 22/10/18
1

Fazer exatamente isso funcionou para mim, para um repositório existente. Isso requer conselhos de várias respostas e comentários antes:

No diretório pai do repositório, no servidor:

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

@stevek_mcc resposta é a que eu estava procurando quando pesquisei esta pergunta no Google

git clone --config core.sharedRepository=true
ragerdl
fonte