Qual é a diferença entre "git init" e "git init --bare"?

162

Qual é a diferença entre git inite git init --bare? Descobri que muitas postagens de blog exigem --barepara o servidor Git?

Na página do manual , dizia:

--bare

Crie um repositório vazio. Se o ambiente GIT_DIR não estiver definido, ele será definido no diretório de trabalho atual

Mas o que isso realmente significa? É necessário ter --barepara a configuração do servidor Git?

Kit Ho
fonte

Respostas:

143

Repositório não-nu do Git

Essa variante cria um repositório com um diretório ativo para que você possa trabalhar ( git clone). Depois de criá-lo, você verá que o diretório contém uma pasta .git, onde estão o histórico e todo o encanamento do git. Você trabalha no nível em que a pasta .git está.

Bare Git Repo

A outra variante cria um repositório sem um diretório ativo ( git clone --bare). Você não recebe um diretório onde pode trabalhar. Agora, tudo no diretório é o que estava contido na pasta .git no caso acima.

Por que você usaria um vs. o outro

A necessidade de repositórios git sem um diretório ativo é o fato de que você pode enviar ramificações para ele e não gerenciar o que alguém está trabalhando. Você ainda pode enviar para um repositório que não está vazio, mas será rejeitado, pois poderá mover potencialmente um ramo em que alguém esteja trabalhando nesse diretório de trabalho.

Portanto, em um projeto sem pasta de trabalho, você só pode ver os objetos como o git os armazena. Eles são compactados e serializados e armazenados sob o SHA1 (um hash) de seu conteúdo. Para obter um objeto em um repositório vazio, você precisa git showespecificar o sha1 do objeto que deseja ver. Você não verá uma estrutura como a aparência do seu projeto.

Repositórios vazios são geralmente repositórios centrais para onde todos movem seu trabalho. Não há necessidade de manipular o trabalho real. É uma maneira de sincronizar esforços entre várias pessoas. Você não poderá ver diretamente os arquivos do seu projeto.

Você pode não ter necessidade de nenhum repositório vazio, se você é o único que trabalha no projeto ou não deseja / precisa de um repositório "logicamente central". Um preferiria git pull dos outros repositórios nesse caso. Isso evita as objeções que o git tem ao enviar para repositórios não vazios.

Espero que isto ajude

Adam Dymitruk
fonte
Mantenha a , jogue fora a partir desta linha - Um preferiria git pull de um outro ... :-)
Arup Rakshit
10
Acho esta resposta muito clara e confusa. Alguns dos motivos estão aqui: meta.stackoverflow.com/questions/339837/…
Marko Avlijaš
Bare repositories are usually central repositories where everyone moves their work to.Você quer dizer que um repositório vazio é a fonte da qual outros colaboradores do projeto podem clonar um projeto? Ou seja, os colaboradores tratam isso como o remote?
Minh Tran
112

Resposta curta

Um repositório vazio é um repositório git sem uma cópia de trabalho; portanto, o conteúdo de .git é de nível superior para esse diretório.

Use um repositório não bare para trabalhar localmente e um repositório bare como servidor / hub central para compartilhar suas alterações com outras pessoas. Por exemplo, quando você cria um repositório no github.com, ele é criado como um repositório simples.

Então, no seu computador:

git init
touch README
git add README
git commit -m "initial commit"

no servidor:

cd /srv/git/project
git init --bare

Em seguida, no cliente, você pressiona:

git push username@server:/srv/git/project master

Você pode salvar a digitação adicionando-a como um controle remoto.

O repositório no lado do servidor receberá confirmações por meio de puxar e enviar, e não editando os arquivos e enviando-os na máquina do servidor, portanto, é um repositório simples.

Detalhes

Você pode enviar para um repositório que não é um repositório vazio, e o git descobrirá que existe um repositório .git, mas como a maioria dos repositórios "hub" não precisa de uma cópia de trabalho, é normal usar um repositório vazio para e recomendado, pois não faz sentido ter uma cópia de trabalho nesse tipo de repositório.

No entanto, se você enviar para um repositório não vazio, estará tornando a cópia de trabalho inconsistente e o git avisará:

remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.

Você pode pular este aviso. Mas a configuração recomendada é: use um repositório não bare para trabalhar localmente e um repositório bare como hub ou servidor central para fazer push e pull.

Se você deseja compartilhar o trabalho diretamente com a cópia de trabalho de outro desenvolvedor, é possível puxar uns dos outros repositórios em vez de empurrar.

duncan
fonte
se eu quiser trabalhar meu projeto no servidor git, não é necessário ter a opção --bare, não é?
Kit Ho
Você usa o bare para o repositório remoto, não para o local.
Duncan
Faz um tempo, mas aqui outra pergunta. Se tivermos um repositório remoto, qualquer desenvolvedor pode fazer um push, e o repositório é "central". Mas se trabalharmos sem um repositório vazio, os desenvolvedores devem se afastar apenas um do outro, mas nunca forçar. O último cenário é bom, se houver apenas duas cópias de trabalho do repositório (também conhecido como repositório local). Isso está correto?
Asturio
60

Quando li essa pergunta há algum tempo, tudo estava confuso para mim. Comecei a usar o git e existem essas cópias de trabalho (que não significavam nada naquele momento). Vou tentar explicar isso da perspectiva do cara, que acabou de começar o git sem nenhuma idéia sobre terminologia.

Um bom exemplo das diferenças pode ser descrito da seguinte maneira :

--barefornece apenas um local de armazenamento (você não pode desenvolver lá). Sem --bareele, você pode se desenvolver lá (e ter um local de armazenamento).

git initcria um repositório git a partir do seu diretório atual. Ele adiciona a pasta .git e possibilita iniciar o histórico de revisões.

git init --baretambém cria um repositório, mas não possui o diretório ativo. Isso significa que você não pode editar arquivos, confirmar suas alterações, adicionar novos arquivos nesse repositório.

Quando --barepode ser útil? Você e alguns outros caras estão trabalhando no projeto e usam o git. Você hospedou o projeto em algum servidor ( amazon ec2). Cada um de vocês tem sua própria máquina e pressiona seu código ec2. Nenhum de vocês realmente desenvolve nada ec2(usa suas máquinas) - basta pressionar seu código. Portanto, você ec2é apenas um armazenamento para todo o seu código e deve ser criado como --baree todas as suas máquinas sem --bare(provavelmente apenas um, e outro apenas clonará tudo). O fluxo de trabalho fica assim:

insira a descrição da imagem aqui

Salvador Dalí
fonte
1
Então, poderíamos dizer que, usando um repositório --bare, podemos criar um tipo de arquitetura cliente-servidor como o subversion faz?
Emiliano Sangoi
14

Um repositório Git padrão assume que você o usará como seu diretório de trabalho. Normalmente, quando você está em um servidor, não precisa ter um diretório ativo. Apenas o repositório. Nesse caso, você deve usar a --bareopção

Sandro Munda
fonte
em um repositório com a opção --bare, para que não possamos ver todo o arquivo do projeto? Parece que eu perco todo o meu arquivo de projeto com opção --bare ..
Kit Ho
11

Um repositório não bare é o padrão. É o que é criado quando você executa git init, ou o que você obtém quando você clona (sem a bareopção) de um servidor.

Ao trabalhar com um repositório como este, você pode ver e editar todos os arquivos que estão no repositório. Quando você interage com o repositório - por exemplo, efetuando uma alteração - o Git armazena suas alterações em um diretório oculto chamado .git.

Quando você possui um servidor git, não é necessário que haja cópias de trabalho dos arquivos. Tudo o que você precisa são os dados do Git armazenados .git. Um repositório vazio é exatamente o .gitdiretório, sem uma área de trabalho para modificar e confirmar arquivos.

Quando você clona de um servidor, o Git tem todas as informações necessárias no .gitdiretório para criar sua cópia de trabalho.

Andrew
fonte
1

Outra diferença entre os repositórios --bare e Working Tree é que, no primeiro caso, nenhuma confirmação perdida é armazenada, mas apenas as confirmações pertencentes a uma faixa de ramificação são armazenadas. Por outro lado, a Working Tree mantém todos os commits para sempre. Ver abaixo...

Eu criei o primeiro repositório (nome: git-bare ) com git init --bare. É o servidor. Está no lado esquerdo, onde não há ramificações remotas, porque este é o próprio repositório remoto.

Eu criei o segundo repositório (nome: git-working-tree ) com git cloneo primeiro. Está à direita. Possui filiais locais vinculadas a filiais remotas.

(Os textos 'primeiro', 'segundo', 'terceiro', 'quarto', 'alfa', 'beta' e 'delta' são os comentários de confirmação. Os nomes 'mestre' e 'grego' são nomes de ramificação.)

Repositórios locais e remotos

Agora vou excluir o ramo chamado 'greek' no git-bare (command git push --delete origin greek:) e localmente no git-working-tree (command git branch -D greek:). Aqui está a aparência da árvore:

O repositório git-bare exclui o que não é mais referenciado

o repositório git-bare exclui a ramificação e todas as confirmações referenciadas. Na figura, vemos que sua árvore foi reduzida por esse motivo.

Por outro lado, o repositório git-working-tree , que é equivalente a um repositório local comumente usado, não exclui confirmações, que agora só podem ser referenciadas diretamente pelo seu hash com umgit checkout 7fa897b7 comando. É por isso que sua árvore não possui sua estrutura modificada.

Em resumo: Compromete nunca são caiu em -árvore de trabalho repositórios, mas são apagadas na nuas repositórios.

Em termos práticos, você pode recuperar apenas uma ramificação excluída no servidor se ela existir em um repositório local.

Mas é muito estranho que o tamanho do bare repositório não diminuir de tamanho em disco após a exclusão de uma filial remota. Ou seja, os arquivos ainda estão lá de alguma forma. Para despejar o repositório excluindo o que não é mais referenciado ou o que nunca pode ser referenciado (o último caso), use o git gc --prunecomando

Sergio Cabral
fonte
Para teste de comandos git tentar: github.com/sergiocabral/App.GitPlayground
Sergio Cabral