Qual é a diferença prática entre um repositório Bare e não Bare?

213

Eu tenho lido sobre os repositórios bare e non-bare / default no Git. Não fui capaz de entender muito bem (teoricamente) sobre as diferenças entre elas e por que devo "empurrar" para um repositório vazio. Aqui está o acordo:

Atualmente, sou o único trabalhando em um projeto em 3 computadores diferentes, mas haverá mais pessoas envolvidas nele mais tarde, então estou usando o Git para o controle de versão. Clono o repositório simples em todos os computadores e, quando termino minhas modificações em um deles, confirmo e envio as alterações ao repositório simples. Pelo que li, o repositório vazio NÃO possui uma "árvore de trabalho", portanto, se eu clonar o repositório vazio, não terei uma "árvore de trabalho".

Suponho que a árvore de trabalho armazene as informações de confirmação, ramificações etc. do projeto. Isso não apareceria no repositório simples. Portanto, parece melhor para mim "enviar" os commits ao repositório com a árvore de trabalho.

Então, por que devo usar o repositório vazio e por que não? Qual a diferença prática? Isso não seria benéfico para mais pessoas trabalhando em um projeto, suponho.

Quais são seus métodos para esse tipo de trabalho? Sugestões?

AeroCross
fonte
4
AeroCross, você pode clonar um repositório vazio para criar um repositório não nu (ou seja, um que tenha um espaço de trabalho). Portanto, git clonevocê pode converter livremente entre repositórios vazios e não vazios.
Derek Mahar
13
@AeroCross: Não se trata de converter; não importa o que está do outro lado. Se você executar, git clone --bareobterá um repositório simples e, se executar git clone, obterá um repositório simples. Todo projeto público que você já clonou (hospedado no github, por exemplo) é um repositório simples do outro lado.
Cascabel
1
Jefromi, eu estava corrigindo o ponto do AeroCross, "então se eu clonar o repositório simples, não terei uma" árvore de trabalho "", portanto é um tipo de conversão. E nem todo projeto público deve ser um repositório simples. É apenas a escolha típica, porque um repositório vazio é mais eficiente em termos de espaço, pois não possui árvore de trabalho (é tão eficiente em termos de espaço quanto qualquer repositório que não possui árvore de trabalho).
Derek Mahar
2
@Derek: Mas o ponto é que, assim que encontra o diretório .git, a busca é totalmente inconsciente se o controle remoto está vazio ou não. Não converte. Ele apenas busca o que precisa no controle remoto e o coloca onde deve ir. Não há nada para converter. Era isso que eu estava tentando enfatizar para o OP. E estou ciente de que os projetos públicos não precisam ser vazios, mas, como as pessoas não são estúpidas, elas essencialmente são. Eu acho que fiz uma generalização aceitável.
quer
2
Consulte Enviar para repositório não bare, o que fornece outra excelente explicação sobre o uso do repositório bare.
Craig McQueen

Respostas:

95

Outra diferença entre um repositório bare e non-bare é que um repositório bare não possui um repositório de origem remoto padrão :

~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Na página de manual para git clone --bare:

Além disso, as cabeças de ramificação no controle remoto são copiadas diretamente para as cabeças de ramificação locais correspondentes, sem mapeá-las para refs / remotes / origin /. Quando essa opção é usada, nem as ramificações de rastreamento remoto nem as variáveis ​​de configuração relacionadas são criadas.

Presumivelmente, quando ele cria um repositório vazio, o Git assume que o repositório vazio servirá como repositório de origem para vários usuários remotos, portanto, não cria a origem remota padrão. O que isso significa é que o básico git pulle as git pushoperações não funcionarão, pois o Git assume que, sem um espaço de trabalho, você não pretende confirmar nenhuma alteração no repositório vazio:

~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$ 
Derek Mahar
fonte
1
Sim, eu concordo que essa é sem dúvida a diferença mais significativa entre repositórios vazios e não vazios do Git. O fato de um repositório não bare ter uma área de trabalho, mas um repositório nu não é uma diferença importante, mas git clone --no-checkoutpode criar um repositório não bare sem arquivos de espaço de trabalho também.
Drek Mahar
10
Um repositório não bare também não necessariamente possui uma "origem" remota padrão.
Mipadi
2
Você pode criar um repositório Git simplesmente com git init, o que criará um repositório não-bare sem controle remoto especificado.
Mipadi
1
mipadi, isso é verdade, mas também não é um clone.
Drek Mahar
1
Isto está incorreto. Um repositório terá uma origem padrão se tiver sido cloneeditado. Se tiver sido initeditado localmente, não terá essa origem. Isso não tem nada a ver com o fato de estar nu ou não.
Noufal Ibrahim
62

A distinção entre um repositório Git vazio e não nu é artificial e enganosa, pois um espaço de trabalho não faz parte do repositório e um repositório não requer um espaço de trabalho. A rigor, um repositório Git inclui os objetos que descrevem o estado do repositório. Esses objetos podem existir em qualquer diretório, mas normalmente existem no .gitdiretório no diretório de nível superior da área de trabalho. O espaço de trabalho é uma árvore de diretórios que representa uma confirmação específica no repositório, mas pode existir em qualquer diretório ou não existir. A variável de ambiente $GIT_DIRvincula um espaço de trabalho ao repositório do qual se origina.

Os comandos Git git clonee git initambos têm opções --bareque criam repositórios sem um espaço de trabalho inicial. É lamentável que o Git combine os dois conceitos separados, mas relacionados, de espaço de trabalho e repositório e, em seguida, use o termo confuso bare para separar as duas idéias.

Derek Mahar
fonte
61

Um repositório vazio nada mais é que a própria pasta .git , ou seja, o conteúdo de um repositório vazio é o mesmo que o conteúdo da pasta .git dentro do seu repositório local de trabalho.

  • Use o repositório vazio em um servidor remoto para permitir que vários colaboradores enviem seus trabalhos.
  • Não-nua - A que possui uma árvore de trabalho faz sentido na máquina local de cada colaborador do seu projeto.
Deepak Sharma
fonte
60

Seis anos atrasado, eu sei, mas ninguém respondeu à pergunta:

Então, por que devo usar o repositório vazio e por que não? Qual a diferença prática? Isso não seria benéfico para mais pessoas trabalhando em um projeto, suponho.

Quais são seus métodos para esse tipo de trabalho? Sugestões?

Para citar diretamente o livro Loeliger / MCullough (978-1-449-31638-9, p196 / 7):

Um repositório simples pode parecer pouco útil, mas seu papel é crucial: servir como um ponto focal autoritativo para o desenvolvimento colaborativo. Outros desenvolvedores clonee fetchdo repositório vazio e as pushatualizações para ele ... se você configurar um repositório no qual os desenvolvedores pushmudam, ele deve estar vazio. Com efeito, este é um caso especial das práticas recomendadas mais gerais que um repositório publicado deve ter.

EML
fonte
19

Um repositório não nu simplesmente possui uma árvore de trabalho com check-out. A árvore de trabalho não armazena nenhuma informação sobre o estado do repositório (ramificações, tags, etc.); em vez disso, a árvore de trabalho é apenas uma representação dos arquivos reais no repositório, o que permite trabalhar (editar, etc.) os arquivos.

mipadi
fonte
Então isso significa que eu posso adicionar ramificações, tags etc. ao repositório vazio e depois puxar do repositório vazio para o não-nu / produção?
AeroCross
2
mipadi, um repositório não nu pode não ter uma árvore de check-out. Este é o caso se você criar um repositório não-nua com git clone --no-checkout. Nesse caso, o repositório não bare possui um local para o espaço de trabalho, mas o Git não faz check-out de nenhum arquivo nesse espaço de trabalho.
Drek Mahar
17

Um repositório bare possui benefícios em

  • uso reduzido do disco
  • menos problemas relacionados ao envio remoto (já que nenhuma árvore de trabalho existe para sair da sincronização ou ter alterações conflitantes)
ver
fonte
3
Portanto, o repositório simples é a melhor / recomendada maneira de trabalhar com várias pessoas sem acesso a seus repositórios? (Kinda como SVN?)
AeroCross
2
AeroCross, eu diria que um repositório vazio é uma boa escolha para esse cenário.
Drek Mahar
12

O repositório não básico permite que você (na sua árvore de trabalho) capture alterações criando novas confirmações.

Repositórios vazios são alterados apenas transportando alterações de outros repositórios.

Nitin
fonte
10

Eu certamente não sou um "especialista" do Git. Eu uso o TortoiseGit há algum tempo e me perguntei do que estava falando quando me perguntou se eu queria fazer um repo "nu" sempre que o criei. Eu estava lendo este tutorial: https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init e aborda o problema, mas ainda não estava entendendo bem o conceito. Este ajudou bastante: http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html . Agora, o primeiro também faz sentido!

De acordo com essas fontes, em poucas palavras, um repositório "bare" é usado em um servidor em que você deseja configurar um ponto de distribuição. Ele não se destina ao uso em sua máquina local. Geralmente, você envia por push as confirmações da sua máquina local para um repositório simples em um servidor remoto e você e / ou outras pessoas extraem desse repositório simples para a sua máquina local. Portanto, seu repositório de armazenamento / distribuição remoto do GitHub, Assembla etc. é um exemplo em que um repositório "simples" é criado. Você mesmo criaria um se estivesse montando seu próprio "centro de compartilhamento" análogo.

BuvinJ
fonte
ooooh agora eu entendi
Fuseteam
9

Um repositório Git padrão / não nu contém duas partes de estado:

  1. Um instantâneo de todos os arquivos no repositório (é o que "árvore de trabalho" significa no jargão do Git)
  2. Um histórico de todas as alterações feitas em todos os arquivos que já existiram no repositório (não parece haver uma parte concisa do jargão do Git que englobe tudo isso)

O snapshot é o que você provavelmente considera seu projeto: seus arquivos de código, arquivos de construção, scripts auxiliares e qualquer outra coisa que você versão com Git.

O histórico é o estado que permite verificar uma confirmação diferente e obter uma captura instantânea completa da aparência dos arquivos no repositório quando a confirmação foi adicionada. Ele consiste em várias estruturas de dados internas ao Git com as quais você provavelmente nunca interagiu diretamente. É importante ressaltar que o histórico não armazena apenas metadados (por exemplo, "O usuário U adicionou tantas linhas ao arquivo F no momento T como parte do commit C"), mas também armazena dados (por exemplo, "o usuário U adicionou essas linhas exatas ao arquivo F" )

A idéia principal de um repositório simples é que você realmente não precisa ter o instantâneo. O Git mantém o snapshot por perto, porque é conveniente para humanos e outros processos que não sejam do Git que desejam interagir com seu código, mas o snapshot está apenas duplicando o estado que já está na história.

Um repositório vazio é um repositório Git que não possui um instantâneo. Apenas armazena a história.

Por que você quer isso? Bem, se você só vai interagir com seus arquivos usando o Git (ou seja, não vai editar seus arquivos diretamente ou usá-los para criar um executável), poderá economizar espaço, não mantendo o snapshot. Em particular, se você estiver mantendo uma versão centralizada do seu repositório em um servidor em algum lugar (por exemplo, hospedando seu próprio GitHub), esse servidor provavelmente deverá ter um repositório simples (você ainda usaria um repositório não nu no seu máquina local, porém, já que você provavelmente desejará editar seu instantâneo).

Se você quiser uma explicação mais aprofundada dos repositórios simples e outro exemplo de caso de uso, escrevi uma postagem no blog aqui: https://stegosaurusdormant.com/bare-git-repo/

Greg Owen
fonte
4

Esta não é uma resposta nova, mas me ajudou a entender os diferentes aspectos das respostas acima (e é demais para um comentário).

Usando o Git Bash, tente:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/

me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 .git/

me@pc MINGW64 /c/Test (master)
$ cd .git

me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr  1 11:35 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:35 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:35 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 objects/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 refs/

Mesmo com git --bare:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/

me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr  1 11:36 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:36 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:36 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 objects/
Christoph
fonte
2

$ git help repository-layout

Um repositório Git vem em dois tipos diferentes:

  • um diretório .git na raiz da árvore de trabalho;
  • um diretório .git que é um repositório vazio (ou seja, sem sua própria árvore de trabalho), que normalmente é usado para trocar históricos com outros, empurrando-o e buscando nele.
MichK
fonte