Qual é a diferença entre git clone --mirror e git clone --bare

486

A página de ajuda do git clone tem a dizer sobre --mirror:

Configure um espelho do repositório remoto. Isso implica --bare.

Mas não entra em detalhes sobre como o --mirrorclone é diferente de um --bareclone.

Sam
fonte
3
útil, mas se você também quiser enviar esse espelho para um repositório remoto como o github, achei esse link útil.
Coma em Joes

Respostas:

569

A diferença é que, ao usar --mirror, todas as referências são copiadas como estão . Isso significa tudo: ramificações de rastreamento remoto, notas, refs / originais / * (backups da ramificação de filtro). O repositório clonado tem tudo. Também é configurado para que uma atualização remota busque tudo da origem (substituindo as referências copiadas). A idéia é realmente espelhar o repositório, ter uma cópia total, para que você possa, por exemplo, hospedar seu repositório central em vários locais ou fazer backup dele. Pense apenas em copiar diretamente o repositório, exceto de uma maneira muito mais elegante.

A nova documentação praticamente diz tudo isso:

--mirror

Configure um espelho do repositório de origem. Isso implica --bare. Comparado a --bare, --mirrornão apenas mapeia ramificações locais da origem para ramificações locais do destino, ele mapeia todas as refs (incluindo ramificações remotas, notas etc.) e define uma configuração refspec de modo que todas essas refs sejam substituídas por uma git remote updateno repositório de destino .

Minha resposta original também observou as diferenças entre um clone nu e um clone normal (não nu) - o clone não nu configura ramificações de rastreamento remoto, criando apenas uma ramificação local HEAD, enquanto o clone nu copia as ramificações diretamente.

Origem Suponha que tem alguns ramos ( master (HEAD), next, pue maint), algumas tags ( v1, v2, v3), algumas filiais remotas ( devA/master, devB/master), e alguns outros refs ( refs/foo/bar, refs/foo/bazque pode ser notas, esconderijos, namespaces de outros devs, quem sabe).

  • git clone origin-url(non-bare): Você vai ter todas as etiquetas copiadas, uma filial local master (HEAD)acompanhamento de um ramo remoto origin/master, e filiais remotas origin/next, origin/pue origin/maint. As ramificações de rastreamento são configuradas para que, se você fizer algo assim git fetch origin, elas sejam buscadas conforme o esperado. Quaisquer ramificações remotas (no controle remoto clonado) e outras referências são completamente ignoradas.

  • git clone --bare origin-url: Você vai ter todas as etiquetas copiadas, filiais locais master (HEAD), next, pu, e maintramificações de controle, sem controle remoto. Ou seja, todas as ramificações são copiadas como estão e são configuradas de forma completamente independente, sem expectativa de buscar novamente. Quaisquer ramificações remotas (no controle remoto clonado) e outras referências são completamente ignoradas.

  • git clone --mirror origin-url: Todos os últimos árbitros serão copiados como estão. Você obterá todas as tags, ramos locais master (HEAD), next, pu, e maint, filiais remotas devA/mastere devB/master, outros refs refs/foo/bare refs/foo/baz. Tudo está exatamente como estava no controle remoto clonado. O rastreamento remoto é configurado para que, se você executar, git remote updatetodos os árbitros sejam substituídos da origem, como se você tivesse excluído o espelho e o refilado. Como os documentos disseram originalmente, é um espelho. Deveria ser uma cópia funcionalmente idêntica, intercambiável com o original.

Cascabel
fonte
"Clone normal" se refere a um clone sem os sinalizadores --bare ou --mirror?
Sam
1
Sim ele faz. Com um clone simples, como diz a página de manual, as ramificações também são copiadas diretamente (sem referências / controles remotos / origem, sem rastreamento). Editado em.
Cascabel
Você pode adicionar mais alguns exemplos de uso sobre a diferença, não apenas sobre as diferenças internas do git?
cmcginty
@ Casey é isso que você estava procurando? Não achei que o que escrevi originalmente fosse "interno" - etiquetas e galhos são características de porcelana.
Cascabel
"Ramificações copiadas como estão" significam que ramificações são copiadas para o mesmo caminho relativo no clone? Ou isso implica que os ramos são transformados de alguma maneira?
Sam
56
$ git clone --mirror $URL

é uma mão curta para

$ git clone --bare $URL
$ (cd $(basename $URL) && git remote add --mirror=fetch origin $URL)

(Copiado diretamente daqui )

Como a página de manual atual coloca:

Comparado a --bare, --mirrornão apenas mapeia ramificações locais da origem para ramificações locais do destino, ele mapeia todas as refs (incluindo ramificações remotas, notas etc.) e define uma configuração refspec de modo que todas essas refs sejam substituídas por uma git remote updateno repositório de destino .

hfs
fonte
4
Eu acredito que você teria que seguir isso com um git fetchpara que ele seja realmente idêntico. Enfim, isso é uma espécie de não resposta - o objetivo da pergunta é "como o clone remoto / clone de um espelho é diferente do normal?"
Cascabel
6
Na verdade, gosto dessa maneira de demonstrar a diferença. Espero que seja preciso! Espero que o hfs adicione o comando buscar.
Joeytwiddle
não é muito claro, por exemplo, o que $ (basename $ URL) está traduzindo etc.
Kzqai 22/10/12
5
basenameé o utilitário unix normal que retira a parte do diretório de um caminho e $()é simplesmente a substituição de comandos do bash.
Victor Zamanian
6
Isso ainda tem --mirrornele. Isso seria apenas uma resposta aceitável se explicasse o que git remote add --mirrorfaz.
Zenexer
24

Meus testes com o git-2.0.0 hoje indicam que a opção --mirror não copia ganchos, o arquivo de configuração, o arquivo de descrição, o arquivo de informações / exclusão e, pelo menos no meu caso de teste, algumas referências (que eu não Eu não chamaria isso de "cópia funcionalmente idêntica, intercambiável com o original".

-bash-3.2$ git --version
git version 2.0.0
-bash-3.2$ git clone --mirror /git/hooks
Cloning into bare repository 'hooks.git'...
done.

-bash-3.2$ diff --brief -r /git/hooks.git hooks.git
Files /git/hooks.git/config and hooks.git/config differ
Files /git/hooks.git/description and hooks.git/description differ
...
Only in hooks.git/hooks: applypatch-msg.sample
...
Only in /git/hooks.git/hooks: post-receive
...
Files /git/hooks.git/info/exclude and hooks.git/info/exclude differ
...
Files /git/hooks.git/packed-refs and hooks.git/packed-refs differ
Only in /git/hooks.git/refs/heads: fake_branch
Only in /git/hooks.git/refs/heads: master
Only in /git/hooks.git/refs: meta
Mark E. Hamilton
fonte
14

Uma explicação detalhada da documentação do GitHub sobre Duplicar um Repositório :

Como em um clone simples, um clone espelhado inclui todas as ramificações e tags remotas, mas todas as referências locais serão substituídas toda vez que você buscar, portanto, sempre será o mesmo que o repositório original.

Feckmore
fonte
1
Obrigado; isso me esclareceu que as tags locais serão substituídas, assim como as ramificações, usando um clone espelhado. Muito útil.
Wildcard
2
Você também pode usar --pruneao executar o git fetch para remover referências locais que não estão mais no controle remoto.
Nishanths
13

Um clone copia os árbitros do controle remoto e os coloca em um subdiretório chamado 'estes são os árbitros que o controle remoto possui'.

Um espelho copia os árbitros do controle remoto e os coloca em seu próprio nível superior - ele substitui seus próprios árbitros pelos do controle remoto.

Isso significa que quando alguém puxa do seu espelho e coloca os árbitros do espelho em seu subdiretório, eles obtêm os mesmos árbitros que estavam no original. O resultado da busca de um espelho atualizado é o mesmo que a busca direta do repo inicial.

PaulMurrayCbr
fonte
12

Eu adiciono uma imagem, mostro a configdiferença entre espelho e nua. insira a descrição da imagem aqui A esquerda está vazia, a direita é espelho. Você pode ser claro: o arquivo de configuração do espelho possui uma fetchchave, o que significa que você pode atualizá-lo, por git remote updateougit fetch --all

yanzi1225627
fonte
3
$ git clone --bare https://github.com/example

Este comando fará do novo o $ GIT_DIR. 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 mapeamento. Quando essa opção é usada, nem ramificações de rastreamento remoto nem as variáveis ​​de configuração relacionadas são criadas.

$ git clone --mirror https://github.com/example

Como em um clone simples, um clone espelhado inclui todas as ramificações e tags remotas, mas todas as referências locais (incluindo ramificações de rastreamento remoto, notas etc.) serão substituídas sempre que você buscar, portanto, sempre será o mesmo que o repositório original .

Shantanu Singh
fonte