Como converter um repositório Git normal em um repositório simples?

603

Como posso converter um repositório Git 'normal' em um repositório simples?

A principal diferença parece ser:

  • no repositório Git normal, você tem uma .gitpasta dentro do repositório contendo todos os dados relevantes e todos os outros arquivos que compõem sua cópia de trabalho

  • em um repositório simples do Git, não há cópia de trabalho e a pasta (vamos chamá-lo repo.git) contém os dados reais do repositório

Boldewyn
fonte
16
Presumivelmente, este é um método mais curto:mv repo/.git repo.git; rm -rf repo
jameshfisher
Sim, verdade. Quando escrevi a pergunta, esse foi apenas o trecho da minha história, que executei no outro minuto.
precisa saber é o seguinte
54
@eegg Use em &&vez de ;em caso de mvfalha!

Respostas:

610

Resumindo: substitua o conteúdo de repopelo conteúdo de repo/.gite diga ao repositório que agora é um repositório simples.

Para fazer isso, execute os seguintes comandos:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Observe que isso é diferente de fazer um git clone --barepara um novo local (veja abaixo).

Jörg W Mittag
fonte
9
Obrigado pela dica core.bare. Agora, depois de pesquisar essa opção no Google, posso confirmá-la: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn
14
Obrigado! Isto parece mais limpo para mim: mv repo / .git repo.git && rm -rf repo && cd repo.git && git configuração --bool core.bare verdade
JasonWoof
56
Isso é muito mais complicado e frágil do que a resposta abaixo ( git clone --bare /path/to/repo).
DJD
7
Esse rmcomando pode precisar, em * \.[!.]*vez de *remover arquivos de ponto e diretórios de ponto.
Minopret
6
@ Ciantic: Novamente, como eu já expliquei no meu comentário acima, minha resposta foi dada há 3 anos, mas há 5 meses alguém editou a pergunta em algo completamente diferente. Nenhum das respostas nesta página fará qualquer sentido. Essa sequência de comandos foi copiada diretamente da pergunta, acabei de adicionar as duas últimas linhas.
Jörg W Mittag
244

Seu método parece que funcionaria; a estrutura de arquivos de um repositório vazio é exatamente o que está dentro do diretório .git. Mas eu não sei se algum dos arquivos foi realmente alterado. Se isso falhar, você pode simplesmente

git clone --bare /path/to/repo

Você provavelmente precisará fazer isso em um diretório diferente para evitar um conflito de nome e, em seguida, basta movê-lo de volta para onde quiser. E pode ser necessário alterar o arquivo de configuração para apontar para onde estiver o repositório de origem.

jonescb
fonte
50
Errado, este método não é equivalente. Fazer um clone não preserva as opções de configuração, o que pode ser crítico para a operação correta, como se você usar o git-p4. Além disso, um clone destrói controles remotos; novamente, com algo como git-p4, você perde a ramificação p4 / master ao clonar, portanto, a abordagem acima é preferível.
nosatalian
26
Mas você pode transferir opções de configuração facilmente, copiando as respectivas partes do arquivo de configuração. Eu ainda consideraria esse método mais limpo do que copiar e renomear arquivos manualmente.
Philipp
6
Isso é perfeito após uma migração do subversion, já que o git-svn não oferece suporte ao --bare.
Keyo 7/01/11
11
Para evitar o conflito de nomes ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja
Isso funciona desde que você execute git update-server-infoo repo bare após a criação.
ACK_stoverflow
116

Eu acho que o seguinte link seria útil

GitFaq: Como faço para deixar nu o repositório não nu existente?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
xhh
fonte
2
Sim, foi exatamente isso que procurei, obrigado! No entanto, a segunda proposta ( git clone) apresenta as desvantagens mencionadas nosatalian acima.
Boldewyn
1
A documentação que você sugeriu continua dizendo: "Um método mais seguro é permitir que o Git lide com todas as configurações internas, fazendo algo como isto ... git clone --bare -l <path_to_repos> <new_dir>"
dafunker em
74

A menos que você deseje ou precise especificamente modificar os bits do sistema de arquivos, é realmente muito simples criar uma versão simples de um repositório não básico (mencionado em vários outros posts aqui). Faz parte da funcionalidade principal do git:

git clone --bare existing_repo_path bare_repo_path

Chip Kaye
fonte
6
É incrível que a melhor resposta de longe tenha 0 votos após> 4 meses. A 'resposta aceita' não muito boa, mas perigosa tem 200!
22813 Stabledog
36
Não é nada surpreendente - essa resposta não faz o que a pergunta original fez. Não converte um repositório, clona um, perdendo informações no processo (por exemplo, ramificações remotas).
GreenAsJade
15

Por favor, considere também usar

git clone --mirror path_to_source_repository

A partir da documentação :

Configure um espelho do repositório de origem. Isso implica --bare. Comparado a --bare, --mirror não apenas mapeia ramificações locais da origem para ramificações locais do destino, ele mapeia todas as refs (incluindo ramificações de rastreamento remoto, notas etc.) e define uma configuração refspec de modo que todas essas refs são substituídos por uma atualização remota do git no repositório de destino.

Jacek Krawczyk
fonte
Parece que esta é a maneira mais concisa, completa e segura de fazer o que o OP deseja (vs. apenas clone). Estou esquecendo de algo? Foi --mirroruma adição relativamente recente?
Craig Silver
@ CraigSilver: Não, como eu vejo no histórico da documentação de tal forma, ele --mirrorestá disponível na versão 1.7, por isso já é bastante longo. Você pode conferir aqui
Jacek Krawczyk
7

Eu só queria enviar para um repositório em um caminho de rede, mas o git não me deixaria fazer isso, a menos que esse repositório fosse marcado como vazio. Tudo que eu precisava era mudar sua configuração:

git config --bool core.bare true

Não é necessário mexer nos arquivos, a menos que você queira mantê-lo limpo.

Slion
fonte
3
Isso é perigoso, quando você também deseja trabalhar na árvore de trabalho do repositório remoto. As chances são de que, mais cedo ou mais tarde, você reverta uma alteração simplesmente porque sua árvore de trabalho remota e seu índice não estavam sincronizados com o repositório. Eu não recomendo esta solução, se você não souber exatamente o que está fazendo.
Boldewyn
É verdade que você não deve trabalhar na árvore do repositório remoto remoto.
Slion 4/03/16
6

Eu li as respostas e fiz isso:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

isso vai deixar o conteúdo de repos/.gitcomo o nurepos.git

Dan D.
fonte
4

Aqui está o que eu acho mais seguro e simples. Não há nada aqui não mencionado acima. Eu só quero ver uma resposta que mostre um procedimento passo a passo seguro. Você inicia uma pasta a partir do repositório (repositório) que deseja exibir. Adotei a convenção implícita acima de que as pastas de repositório vazio têm uma extensão .git.

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
sdesciencelover
fonte
1
isso não é muito mais seguro desde que você fez seu backup usando o git clone. O backup por clonagem fará com que você perca algumas configurações, o que, em certos casos, pode ser crítico para o repositório.
Lie Ryan
Notado. As únicas configurações com as quais me importo são globais para todos os meus repositórios locais.
precisa saber é o seguinte
4

Basta ler

Pro Git Book: 4.2 Git no servidor - Obtendo o Git em um servidor

que se resumem a

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Em seguida, coloque my_project.git no servidor

Qual é principalmente, qual resposta # 42 tentou apontar. Shuring alguém poderia reinventar a roda ;-)

apos
fonte
Não vejo, o que essa resposta acrescenta, que não foi discutido em tamanho arbitrário em nenhuma das outras respostas ao redor (incluindo as votadas abaixo). Você poderia por favor esclarecer? (A propósito: o Git Book Pro diz “Isto é aproximadamente equivalente a algo como ...” , e que a equivalência exata áspera também é já discutido aqui.)
Boldewyn
3

Aqui está uma pequena função BASH que você pode adicionar ao seu .bashrc ou .profile em um sistema baseado em UNIX. Uma vez adicionado, o shell é reiniciado ou o arquivo é recarregado por meio de uma chamada para source ~/.profileou source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Uma vez chamado dentro de um diretório que contém um diretório .git, ele fará as alterações apropriadas para converter o repositório. Se não houver um diretório .git presente quando chamado, uma mensagem FAILURE aparecerá e nenhuma alteração no sistema de arquivos ocorrerá.

nyteshade
fonte
1

Os métodos que dizem para remover arquivos e mexer com a movimentação do diretório .git não são limpos e não usam o método "git" para fazer algo que deve ser simples. Este é o método mais limpo que encontrei para converter um repositório normal em um repositório simples.

Primeiro clone / caminho / para / normal / repo em um repo bare chamado repo.git

git clone --bare /path/to/normal/repo

Em seguida, remova a origem que aponta para / path / to / normal / repo

cd repo.git
git remote rm origin

Finalmente, você pode remover seu repo original. Você pode renomear repo.git para repo nesse ponto, mas a convenção padrão para significar um repositório git é algo.git, então eu pessoalmente deixaria assim.

Depois de fazer tudo isso, você pode clonar seu novo repo bare (que na verdade cria um repo normal e também é como você o converteria de nu para normal)

Obviamente, se você tiver outros fluxos upstream, anote-os e atualize seu repositório simples para incluí-lo. Mas, novamente, tudo pode ser feito com o comando git. Lembre-se de que as páginas de manual são suas amigas.

krux
fonte
1
Você se preocupou em ler as outras respostas? Especialmente o comentário de @ jonescb e @ nosatalian? O método "git" é o seguinte: "Faça o máximo possível com arquivos de texto sem formatação". Você deve começar a investigar as partes internas de uma .gitpasta. É altamente educativo aprender como as peças se encaixam.
precisa saber é o seguinte
1

Caso você tenha um repositório com poucas filiais de check-out local / refs / heads / * e poucas filiais remotas de controle remoto / origem / * E se desejar converter isso em um repositório BARE com todas as filiais em / refs / heads / *

você pode fazer o seguinte para salvar o histórico.

  1. criar um repositório vazio
  2. cd no repositório local que possui filiais de check-out locais e filiais remotas
  3. git push / path / to / bare / repo + refs / remotes / origin / : refs / heads /
Senthil A Kumar
fonte
0

Usei o script a seguir para ler um arquivo de texto que possui uma lista de todos os meus repositórios SVN e convertê-los em GIT, e mais tarde usei o git clone --bare para converter em um repositório simples do git

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt tem o formato

repo1_name
repo2_name

e users.txt tem o formato

(no author) = Prince Rogers <[email protected]>

www-data é o usuário do servidor web Apache, é necessária permissão para enviar alterações por HTTP

Pedro Vicente
fonte
0

Aqui está a definição de um repositório vazio do gitglossary :

Um repositório vazio normalmente é um diretório nomeado adequadamente com um sufixo .git que não possui uma cópia com check-out local de nenhum dos arquivos sob controle de revisão. Ou seja, todos os arquivos administrativos e de controle do Git que normalmente estariam presentes no subdiretório .git oculto estão diretamente presentes no diretório repository.git, e nenhum outro arquivo está presente e com check-out. Normalmente, os editores de repositórios públicos disponibilizam repositórios simples.

Cheguei aqui porque estava brincando com um "repositório local" e queria poder fazer o que quisesse como se fosse um repositório remoto. Eu estava apenas brincando, tentando aprender sobre o git. Assumirei que esta é a situação para quem quiser ler esta resposta.

Eu adoraria para peritagem ou alguns contra-exemplos específicos, no entanto, parece que (depois de vasculhar algum código fonte git que eu encontrei) simplesmente indo para o arquivo .git/confige definindo o núcleo atributo desnudar a verdade , git vai deixar você fazer o que você deseja fazer no repositório remotamente. Ou seja, as seguintes linhas devem existir em .git/config:

[core]
    ...
    bare = true
...

(Isso é aproximadamente o que o comando git config --bool core.bare truefará, o que provavelmente é recomendado para lidar com situações mais complicadas)

Minha justificativa para essa afirmação é que, no código-fonte git, parece haver duas maneiras diferentes de testar se um repositório está vazio ou não. Uma é verificar uma variável global is_bare_repository_cfg. Isso é definido durante alguma fase de instalação da execução e reflete o valor encontrado no .git/configarquivo. O outro é uma função is_bare_repository(). Aqui está a definição desta função:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

Eu não tenho o tempo nem experiência para dizer isso com absoluta confiança, mas, tanto quanto eu poderia dizer se você tem o bareconjunto de atributos para truenos .git/config, este deve sempre retornar 1. O restante da função provavelmente é para a seguinte situação:

  1. core.bare é indefinido (isto é, nem verdadeiro nem falso)
  2. Não há árvore de trabalho (ou seja, o subdiretório .git é o diretório principal)

Vou experimentar com isso quando puder mais tarde, mas isso parece indicar que a configuração core.bare = true é equivalente a remover core.bare do arquivo de configuração e configurar os diretórios corretamente.

De qualquer forma, definir core.bare = true certamente permitirá que você faça isso, mas não tenho certeza se a presença de arquivos de projeto fará com que algumas outras operações dêem errado. É interessante e suponho instrutivo ir ao repositório e ver o que aconteceu localmente (ou seja, executar git statuse entender os resultados).

Nathan Chappell
fonte
-1

Primeiro, backupseu repo existente:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Segundo, execute o seguinte:

git clone --bare -l non_bare_repo new_bare_repo
Shaks
fonte
Para que serve o clone intermediário?
22813 Stabledog
-4

Oneliner para executar todas as operações acima:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(não me culpe se algo explodir e você não tiver backups: P)

Tarmo
fonte
-9

Uau, é simplesmente incrível quantas pessoas concordaram com isso, especialmente considerando que não parece que ninguém parou para perguntar por que essa pessoa está fazendo o que está fazendo.

A ÚNICA diferença entre um repositório bare e não nu é que a versão não nua possui uma cópia de trabalho. A principal razão pela qual você precisaria de um repositório simples é que, se você quisesse disponibilizá-lo para terceiros, não poderá trabalhar diretamente nele, então, em algum momento, será necessário cloná-lo. de volta para uma versão regular da cópia de trabalho.

Dito isto, para converter em um repositório simples, tudo o que você precisa fazer é garantir que você não tenha confirmações pendentes e apenas:

rm -R * && mv .git/* . && rm -R .git

Lá vai você, repositório vazio.

Justin Buser
fonte
11
Isso não deixará claro o suficiente. Tente empurrar para ele. Você precisa fazer git config core.bare truetambém.
Antony Hatchkins
Eu não diminuí o voto, mas gostaria apenas de salientar que a primeira parte desta resposta que explica por que você deseja um repositório simples versus um não básico está ok , embora não contenha detalhes técnicos suficientes e possa seja um pouco impreciso. No entanto , para a 2ª parte da sua resposta, enquanto esses comandos configuram seu repositório para ficar vazio, Anthony está certo , você ainda precisa configurá-lo git config core.bare true, como nesta resposta .