Qual é a melhor prática para “git clone” em uma pasta existente?

480

Eu tenho uma cópia de trabalho do projeto, sem nenhum metadado de controle de origem. Agora, eu gostaria de fazer o equivalente ao git-clone nessa pasta e manter minhas alterações locais.

O git-clone não me permite clonar em uma pasta existente. Qual é a melhor prática aqui?

ripper234
fonte
4
Melhor discussão está aqui .
cdunn2001
1
@MEM I como esta resposta mais, mas de qualquer obras ... stackoverflow.com/a/5377989/11236
ripper234
2
@ ripper234 - Sim. Eu estava na mesma situação e acabei de executar essas etapas, sem problemas. Tudo limpo e agradável. Eu acho que é uma questão de preferência, o ponto principal é que ambos funcionam, como você afirma. Felicidades.
MEM
1
Isso é tão louco que não existe uma maneira limpa de alcançá-lo, tão útil quando você deseja clonar um projeto em uma pasta de compartilhamento montada.
Thomas Decaux
1
Possível duplicata de Como clonar em um diretório não vazio?
Tobias Kienzler 15/08

Respostas:

559

Isso pode ser feito clonando em um novo diretório e movendo o .gitdiretório para o diretório existente.

Se o seu diretório existente tiver o nome "código".

git clone https://myrepo.com/git.git temp
mv temp/.git code/.git
rm -rf temp

Isso também pode ser feito sem fazer um checkout durante o comando clone; mais informações podem ser encontradas aqui .

amicitas
fonte
25
Observe que essa é exatamente a sugestão de @ChrisJohnsen que ele deixou nos comentários. Achei útil e queria transformá-lo em uma resposta real. Chris, se você acabar respondendo, eu excluirei esta.
Amicitas
2
Obrigado! Embora esteja faltando uma etapa como "git checkout -." pois acha que todos os arquivos foram excluídos, certo?
Mroney
2
Não, desde que você use git clonecomo o primeiro comando, nenhum comando adicional de checkout será necessário. Se você usar algo como git clone --no-checkouto primeiro passo, depois que o diretório .git for movido, será necessário usar git reset HEADpara informar ao git que os arquivos não foram excluídos.
Amicitas
3
Gostaria de acrescentar isso como terceiro passo: temp mv / .gitignore código / .gitignore
Daniel Aranda
1
@KalpeshSoni, sim, o git saberá sobre os arquivos modificados e será possível ver as alterações usando os comandos normais do git, como git status.
Amicitas
284

Não clone, busque. No repositório:

git init
git remote add origin $url_of_clone_source
git fetch origin
git checkout -b master --track origin/master # origin/master is clone's default

Em seguida, você pode redefinir a árvore para obter a confirmação que deseja:

git reset origin/master # or whatever commit you think is proper...

e você é como se você fosse clonado.

A questão interessante aqui (e a que não tem resposta): Como descobrir em qual commit sua árvore nua foi baseada, daí para qual posição redefinir.

Andreas Krey
fonte
7
Eu não sou fã disso - por configuração do github "Dica: o assistente de credencial só funciona quando você clona um URL de repositório HTTPS". Eu estava usando um assistente de credencial e isso me levou a uma toca de coelho longa e bastante infrutífera.
Andrew
5
'git checkout --track origin / master' também funciona bem em vez de 'git checkout -b master --track origin / master'. A redefinição não é necessária.
Felipecrp
1
Eu estava recebendo o erro "Git erro: Os seguintes arquivos de árvore de trabalho untracked seria substituído por checkout", então eu adicionar este comando: git -fx -d limpo ""
shakaran
1
definitivamente não é aconselhável em todas as situações, mas é exatamente isso que eu precisava.
Chaim Eliyah
1
@AndreasKrey Sua resposta original (que eu entrei no histórico de edições para ver) faz exatamente o que é necessário para a pergunta (e eu). A resposta alterada vomita no caixa sem usar -f, que descarta as alterações locais e é exatamente o que eu não quero. Se eu fosse você, consideraria voltar à sua resposta original.
Ajean
77

A seguir, fiz o checkout da filial principal em um diretório existente:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft
alexwenzel
fonte
2
Esta é uma ótima resposta e evita qualquer financeamento de sistema de arquivos.
user151841
1
Essa deve ser a resposta aceita, pois não é um hack.
Php_nub_qq
5
Na verdade, isso faz exatamente o que o OP (e eu) não queremos, que é substituir as alterações locais.
Ajean
Meu voto positivo indica que isso me ajudou, não que essa seja a melhor resposta para a pergunta do OP.
TecBrat
2
Alguém pode explicar por que a -tbandeira é usada aqui?
jfowkes
38

Gostaria git clonede um novo diretório e copie o conteúdo do diretório existente para o novo clone.

jhwist
fonte
4
se você fizer isso, analise o diff antes de confirmar com muito cuidado - este é um caso clássico absoluto em que você pode reverter acidentalmente as alterações que foram feitas no repositório de origem desde que você tenha sua cópia de trabalho - porque não há informações suficientes na cópia de trabalho para descobrir quais são as alterações que você fez e como era antes de começar a fazer alterações, para mesclar-se com outras alterações feitas no repositório. Eu já vi isso acontecer uma e outra vez nessa situação, a ponto de eu "fortemente desencorajar" a mim mesmo e às pessoas com quem trabalhei.
Ben Clifford
72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpEm outras palavras, mover o .gitdir de um clone temporário parece mais simples do que limpar a árvore de trabalho do clone e copiar os arquivos existentes lá.
22611 Chris Johnsen
1
@ChrisJohnsen: você deve ter feito isso em uma resposta, que é definitivamente a melhor maneira de fazê-lo IMHO
Stefano
2
@ChrisJohnsen git mv tmp/.git .volta fatal: cannot move directory over file, source=tmp/.git, destination=.gitpara mim. Alguém sabe qual é o problema?
Dennis
6
@ Dennis, é um erro de digitação: esse comando deve ser claro mv, não git mv; embora isso não explique por que você já possui um .gitarquivo (contendo gitdir: some/path/to/a/git-dirum "gitfile"; se ele não estivesse lá, você o teria visto fatal: Not a git repository (or any of the parent directories): .git).
31412 Chris Chrissen
34

Usar um diretório temporário é bom, mas isso funcionará se você desejar evitar essa etapa. Na raiz do seu diretório de trabalho:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master
user1055643
fonte
20
git reset --hard origin/masterirá remover todos os arquivos locais.
Mouad Debbar
1
para adicionar ao que já foi apontado acima, a diferença entre harde mixedé que o misto manterá as alterações locais (por isso, se você tentar puxá-lo mais tarde, ele mostrará, por exemplo: Não é possível puxar com rebase: você tem alterações sem etapas. Confirme ou esconda-as ) , enquanto difícil descartará essas alterações locais
aexl 11/06/19
Você escreveu errado remotamente.
Glenn Dayton
10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed
return1.at
fonte
7
O uso git reset --hardirá alterar as alterações do arquivo local, especificamente NÃO o que este OP solicitou. --mixeddeve ser usado em seu lugar.
Caleb
4

Para clonar um repositório git em um diretório existente vazio, faça o seguinte:

cd myfolder
git clone https://myrepo.com/git.git . 

Observe o .no final do seu git clonecomando. Isso fará o download do repositório no diretório de trabalho atual.

okTalk
fonte
4
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler
O diretório deve estar vazio.
precisa
4
O OP está pedindo como clonar em um projeto existente, afirmando que o clone do git reclama. Resposta ruim.
mix3d
Isso funciona somente quando você criar uma nova pasta, execute os comandos acima sem usar "git init"
Bilal Ahmed
3

Já existem muitas respostas para fazê-lo da maneira que o OP pediu. Mas vale a pena notar que fazer o contrário é muito mais simples:

git clone repo-url tmp/
cp -R working/ tmp/

Agora você tem o estado de destino desejado - novo clone + alterações locais.

Andrew
fonte
2

Existem duas abordagens para isso. Sempre que possível, eu começaria com uma pasta limpa para o seu novo diretório de trabalho do git e depois copiaria sua versão das coisas mais tarde. Isso pode parecer algo como *:

mv $dir $dir.orig
git clone $url $dir
rsync -av --delete --exclude '.git' $dir.orig/ $dir/
rm -rf $dir.orig

Nesse ponto, você deve ter uma cópia de trabalho bastante limpa com sua pasta de trabalho anterior como o diretório de trabalho atual, para que quaisquer alterações, incluindo exclusões de arquivos, apareçam no radar se você executar git status .

Por outro lado, se você realmente deve fazer o contrário, pode obter o mesmo resultado com algo assim:

cd $dir
git clone --no-checkout $url tempdir
mv tempdir/.git .
rmdir tempdir
git reset --mixed HEAD

De qualquer forma, a primeira coisa que eu faria é executar algo como git stash obter uma cópia de todas as suas alterações locais, depois você poderá reaplicá-las e trabalhar com as quais deseja se comprometer.

* Ambos os exemplos pressupõem que você comece no shell no diretório pai do seu projeto.

Caleb
fonte
2

Este é o melhor de todos os métodos que me deparei

Clone apenas a pasta .git do repositório (excluindo os arquivos já existentes existing-dir) em um diretório temporário vazio

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // pode querer --no-hardlinks para clonagem de repositório local

Mova a pasta .git para o diretório com os arquivos. Isso existing-dircria um repositório Git.

  1. mv existing-dir/existing-dir.tmp/.git existing-dir/

Exclua o diretório temporário

  1. rmdir existing-dir/existing-dir.tmp

  2. cd existing-dir

O Git pensa que todos os arquivos foram excluídos, isso reverte o estado do repositório para HEAD.

AVISO: quaisquer alterações locais nos arquivos serão perdidas.

  1. git reset --mixed HEAD
Amirtha Rajan
fonte
1
Uma redefinição definitiva parece indesejada em 99% dos casos em que você precisaria fazer isso.
Stefan Fabian
0

Se você estiver usando pelo menos o git 1.7.7 (que ensinou clonea --configopção), para transformar o diretório atual em uma cópia de trabalho:

git clone example.com/my.git ./.git --mirror --config core.bare=false

Isso funciona por:

  • Clonando o repositório em uma nova .gitpasta
  • --mirrortransforma o novo clone em uma pasta puramente de metadados, conforme .gitnecessário
  • --config core.bare=falsecontrola o implícito bare=trueda --mirroropção, permitindo que o repositório tenha um diretório de trabalho associado e atue como um clone normal

Obviamente, isso não funcionará se um .gitdiretório de metadados já existir no diretório que você deseja transformar em uma cópia de trabalho.

ThorSummoner
fonte
1
Note que esta técnica resultará na [core]seção da configuração local incluindo ambos bare = true e bare = false . Mais problemático é que ele terá os valores incorretos para o origincontrole remoto, com a [remote "origin"]seção incluindo mirror = truee uma especificação de busca que não funcionará corretamente com uma cópia de trabalho. Após corrigir esses problemas, a clonagem normal e a movimentação das novas cópias de trabalho .gitterão sido mais eficientes.
Araxia 15/08/14
0

Normalmente, clonarei primeiro o repositório inicial e depois moverei tudo na pasta existente para o repositório inicial. Funciona sempre.

A vantagem desse método é que você não perderá nada do repositório inicial, incluindo README ou .gitignore.

Você também pode usar o comando abaixo para concluir as etapas:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo
Mike Chen
fonte
0

Você pode fazer isso digitando as seguintes linhas de comando recursivamente:

mkdir temp_dir   //  Create new temporary dicetory named temp_dir
git clone https://www...........git temp_dir // Clone your git repo inside it
mv temp_dir/* existing_dir // Move the recently cloned repo content from the temp_dir to your existing_dir
rm -rf temp_dir // Remove the created temporary directory
MUSTAPHA GHLISSI
fonte
0

Basta usar o. no final do git clonecomando (estando nesse diretório), assim:

cd your_dir_to_clone_in/
git clone [email protected]/somerepo/ .
John F
fonte