Como clonar em um diretório não vazio?

573

Eu tenho o diretório A com os arquivos correspondentes ao diretório B. O diretório A pode ter outros arquivos necessários. O diretório B é um repositório git.

Eu quero clonar o diretório B no diretório A, mas o git-clone não me permite, pois o diretório não está vazio.

Eu esperava que clonasse .git e, como todos os arquivos correspondem, eu poderia ir de lá?

Não consigo clonar em um diretório vazio porque tenho arquivos no diretório A que não estão no diretório B e quero mantê-los.

Copiar .git não é uma opção, pois quero que os árbitros pressionem / puxem e não quero configurá-los manualmente.

Há alguma maneira de fazer isso?

Atualização: Eu acho que isso funciona, alguém pode ver algum problema? ->

cd a
git clone --no-hardlinks --no-checkout ../b a.tmp 
mv a.tmp/.git .
rm -rf a.tmp
git unstage # apparently git thinks all the files are deleted if you don't do this
Dale Forester
fonte
5
talvez você possa mudar a resposta aceita?
Bastiaan Quast

Respostas:

724

Isso funcionou para mim:

git init
git remote add origin PATH/TO/REPO
git fetch
git reset origin/master  # Required when the versioned files existed in path before "git init" of this repo.
git checkout -t origin/master

NOTA: -t definirá a ramificação upstream para você, se é isso que você deseja, e geralmente é.

cmcginty
fonte
70
Isso não funciona em um diretório não vazio quando os arquivos recebidos já existem (como a pergunta original descreve). Mas se você git reset origin/masterapós o trabalho git fetch, ele funcionará (também preservando as alterações locais).
Araxia
8
fatal: Não é possível atualizar os caminhos e alternar para o ramo 'mestre' ao mesmo tempo.
19415 Arnold Roa
7
Esta resposta não funciona para mim. Quando o git checkout ...git reclama que todos os meus arquivos seriam substituídos, devo movê-los primeiro. Quando eu faço `git reset origin / master /` primeiro, o comando checkout reclama que um ramo chamado master já existe.
Saskia
4
git checkout masterfoi um passo final suficiente para mim.
yoyo
16
Todos os passos funcionou perfeitamente, mas o último me pegou: fatal: A branch named 'master' already exists. Eu acho que realmente não precisava disso.
Shadi 20/10
164

Nos comandos shell a seguir, existing-dirhá um diretório cujo conteúdo corresponde aos arquivos rastreados no repo-to-clonerepositório git.

# Clone just the repository's .git folder (excluding files as they are already in
# `existing-dir`) into an empty temporary directory
git clone --no-checkout repo-to-clone existing-dir/existing-dir.tmp # might want --no-hardlinks for cloning local repo

# Move the .git folder to the directory with the files.
# This makes `existing-dir` a git repo.
mv existing-dir/existing-dir.tmp/.git existing-dir/

# Delete the temporary directory
rmdir existing-dir/existing-dir.tmp
cd existing-dir

# git thinks all files are deleted, this reverts the state of the repo to HEAD.
# WARNING: any local changes to the files will be lost.
git reset --hard HEAD
Dale Forester
fonte
5
Eu precisava fazer git reset --hard HEADou não desistiria dos arquivos "excluídos".
Dimitar
18
git reset HEADfuncionou bem para mim. git reset --hard HEADdestrói quaisquer alterações em seus arquivos; portanto, se elas não são exatamente iguais aos arquivos no repositório, você não deve fazer isso.
Tgr 19/12/12
1
git reset HEADnão parece ter nenhum efeito para mim. git reset --hard HEADfaz - mas isso perde as alterações que você fez nos arquivos. Existe uma solução melhor?
27413 Jacob Jacobman
1
A resposta de @ Casey - git init / remote add / fetch / checkout - é mais limpa e simples e não requer pastas temporárias.
yoyo
1
A resposta de @ Casey não funcionou para mim quando já havia arquivos em pastas que precisavam permanecer, mas que não estavam no repositório git. Isso é útil para atualizar a configuração após executar scripts de instalação nos quais arquivos e diretórios são criados, mas você precisa atualizar / adicionar arquivos sobre os itens instalados.
soulston
104

Uma pequena modificação em uma das respostas que funcionaram para mim:

git init
git remote add origin PATH/TO/REPO
git pull origin master

para começar a trabalhar no ramo mestre imediatamente.

mohsaied
fonte
1
tinha que fazer --hard CABEÇA reset para limpar o sujo diretório existente, sem necessidade de remover os arquivos irrelevantes especificados no gitignore
Ray Foss
1
Este é o que realmente funcionou para mim, em oposição à resposta do @ cmcginty.
certainlyakey
4
Isso não é equivalente a um clone do git - o que está faltando são as informações upstream do ramo mestre. Isso pode ser corrigido adicionando git branch --set-upstream-to=origin/master master.
Slaven Rezic
Esta versão funcionou para mim, só tive que fazer um reset no git --hard HEAD
Frédéric Klee
29

Aviso - isso pode sobrescrever arquivos.

git init     
git remote add origin PATH/TO/REPO     
git fetch     
git checkout -t origin/master -f

Modificado a partir da resposta de @ cmcginty - sem o -f não funcionou para mim

JohnFF
fonte
Certamente você precisa fazer o checkout de todos os arquivos depois disso com git checkout .?
Chris Stryczynski
25

Aqui está o que acabei fazendo quando tive o mesmo problema (pelo menos acho que é o mesmo problema). Entrei no diretório A e corri git init.

Como não queria que os arquivos no diretório A fossem seguidos pelo git, editei .gitignore e adicionei os arquivos existentes. Depois disso, corri git remote add origin '<url>' && git pull origin masteret voíla, B é "clonado" em A sem um único soluço.

BjornSnoen
fonte
2
Essa técnica não funciona em um diretório não vazio quando os arquivos recebidos já existem (como a pergunta original descreve).
Araxia 15/08/14
11

Eu usei isso alguns momentos atrás, requer os comandos menos potencialmente destrutivos:

cd existing-dir
git clone --bare repo-to-clone .git
git config --unset core.bare
git remote rm origin
git remote add origin repo-to-clone
git reset

E voilá!

KuttKatrea
fonte
10

Outra receita simples parece funcionar bem para mim:

git clone --bare $URL .git
git config core.bare false

Meu principal caso de uso para acessar um diretório com arquivos existentes é controlar meus arquivos de ponto do Unix com o Git. Em uma nova conta, o diretório inicial já terá alguns arquivos, possivelmente até os que eu quero obter do Git.

Ken Williams
fonte
1
Repositórios vazios são configurados de maneira um pouco diferente e, embora isso funcione, eu não o recomendaria. :)
ThorSummoner 17/02
1
Você pode ser mais específico? O que está diferente?
Ken Williams
1
Apenas duas diferenças: 1.) O .git/configarquivo indica que os repositórios estão vazios. 2.) Os arquivos normalmente armazenados .gitsão armazenados na raiz (que você chamou .git)
mozey
4
Essas são exatamente as mudanças que a clonagem para .gite definir core.barea falsevai cuidar, então eu ainda se sentir bem sobre este método.
Ken Williams
10

Isso funcionou para mim:

cd existing_folder
git init
git remote add origin path_to_your_repo.git
git add .
git commit
git push -u origin master
Mike6679
fonte
6

Eu tive um problema semelhante com um novo diretório da web Apache (conta criada com WHM) que planejei usar como um servidor da Web de teste. Inicialmente, eu precisava clonar meu novo projeto com a base de código e implantar periodicamente as alterações, retirando do repositório.

O problema era que a conta já continha arquivos do servidor da web, como:

.bash_history
.bash_logout
.bash_profile
.bashrc
.contactemail
.cpanel/
...

... que eu não queria excluir ou confirmar no meu repositório. Eu precisava deles para ficar lá sem palco e sem controle.

O que eu fiz:

Eu fui para minha pasta da web (pasta existente):

cd /home/existing_folder

e depois:

git init
git remote add origin PATH/TO/REPO
git pull origin master
git status

Ele exibia (como esperado) uma lista de muitos arquivos não testados - aqueles que já existiam inicialmente na minha conta da web do cPanel.

Então, graças a este artigo , adicionei a lista desses arquivos a:

**.git/info/exclude**

Esse arquivo, quase como o .gitignorearquivo, permite que você ignore os arquivos que estão sendo preparados. Depois disso, eu não tinha mais nada para confirmar no diretório .git / - ele funciona como um pessoal .gitignoreque ninguém mais pode ver.

Agora verificando git statusretornos:

On branch master
nothing to commit, working tree clean

Agora eu posso implantar alterações neste servidor da Web, simplesmente retirando do meu repositório git. Espero que isso ajude alguns desenvolvedores da Web a criar facilmente um servidor intermediário.

Vlado
fonte
5

Aqui está o que estou fazendo:

git clone repo /tmp/folder
cp -rf /tmp/folder/.git /dest/folder/
cd /dest/folder
git checkout -f master
Philip Kirkbride
fonte
4

Talvez eu tenha entendido mal a sua pergunta, mas não seria mais simples se você copiar / mover os arquivos de A para o repositório git B e adicionar os necessários com o git add ?

ATUALIZAÇÃO: No documento git:

A clonagem em um diretório existente é permitida apenas se o diretório estiver vazio.

FONTE: http://git-scm.com/docs/git-clone

Roberto Aloi
fonte
2
Não, o proprietário e os arquivos podem ser arbitrários. Isto é para uma situação com vários desenvolvedores. Todos nós temos diretórios existentes e apenas um atualmente possui um checkout do git. Todos temos em grande parte o mesmo subconjunto de arquivos, portanto, queremos que os outros desenvolvedores possam clonar enquanto retêm seus arquivos. E deve ser o mais elegante e conveniente possível.
Dale Forester
Honestamente, não vejo o ponto de me desenvolver em tal condição. Você não pode usar operações de ramificação e mesclagem? Ou ter sub-repositórios com dependências externas? Por que você deseja confiar em um único "check-out git"?
Roberto Aloi
5
Um "checkout git único" não é o objetivo de todo o calvário. Só que é assim e precisamos de uma maneira de avançar. Atualizei a pergunta original com uma solução que parece estar funcionando. Agradeço o feedback, no entanto.
Dale Forester
3
Existem muitos casos legítimos para isso - eu tenho uma árvore de pastas complexa que precisa ser configurada ANTES que a fonte do meu projeto possa ser configurada e essa árvore de pastas contém trabalhos licenciados que não podem ser armazenados no GitHub, por exemplo.
BrainSlugs83
3

Eu estava procurando por algo semelhante, e aqui está o que eu vim com:

Minha situação é aquela em que tenho uma árvore da web ativa e eu estava tentando criar um repositório remoto para ela sem mover nenhum dos arquivos da árvore da web atual. Aqui está o que eu fiz:

  1. Vá para a árvore da web e execute git init
  2. Vá para o local pretendido do repositório e execute: git clone --bare /path/to/web/repo
  3. Edite o arquivo de configuração no meu repositório remoto e remova a [remote "origin"]seção.
  4. Adicione uma [remote "origin"]seção ao .git / config na árvore da web apontando para o novo repositório remoto.
Lendrick
fonte
Eu gosto muito desta receita.
dland
O git clone --bareaqui é supérfluo e tortuoso. Por que não apenas git remote add origin <URL>em primeiro lugar?
Araxia 15/08/14
3

isso é bom para mim, mas você deve mesclar os arquivos do repositório remoto aos arquivos locais:

git init
git remote add origin url-to-git
git branch --set-upstream-to=origin/master master
git fetch
git status
RODNEY ZHANG
fonte
1

Gostei da resposta de Dale e também adicionei

git clone --depth 2 --no-checkout repo-to-clone existing-dir/existing-dir.tmp
git branch dev_new214
git checkout dev_new214
git add .
git commit
git checkout dev
git merge dev_new214

A profundidade rasa evitou muitos commits extras extras. O novo ramo nos deu uma boa história visual de que havia algum código novo desse servidor que foi colocado. Esse é o ramo de uso perfeito na minha opinião. Meus agradecimentos à grande visão de todas as pessoas que postaram aqui.

Dmitri R117
fonte
0

Eu tenho os mesmos problemas ao tentar clonar em c / code

Mas essa pasta contém vários projetos.

Criei uma nova pasta em c / code / newproject e mapeei meu clone para essa pasta.

O git para desktop pediu o meu usuário e clonou bem.

Tom
fonte