Qual è la migliore pratica per "clonare git" in una cartella esistente?


480

Ho una copia funzionante del progetto, senza metadati di controllo del codice sorgente. Ora, vorrei fare l'equivalente di git-clone in questa cartella e mantenere le mie modifiche locali.

git-clone non mi permette di clonare in una cartella esistente. Qual è la migliore pratica qui?


4
Una discussione migliore è qui .
cdunn2001,

1
@MEM Mi piace questa risposta di più, ma in entrambi i lavori ... stackoverflow.com/a/5377989/11236
ripper234

2
@ ripper234 - Sì. Ero nella stessa situazione e ho appena fatto quei passaggi e nessun problema. Tutto pulito e carino. Immagino sia una questione di preferenza, essendo la linea di fondo, che entrambe funzionano, come dici tu. Saluti.
MEM

1
È così folle che non esiste un modo pulito per raggiungerlo, così utile quando si desidera clonare un progetto in una cartella condivisa montata.
Thomas Decaux,

Risposte:


559

Questo può essere fatto clonando in una nuova directory, quindi spostando la .gitdirectory nella directory esistente.

Se la directory esistente è denominata "codice".

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

Questo può essere fatto anche senza fare un checkout durante il comando clone; maggiori informazioni possono essere trovate qui .


25
Nota che questo è esattamente il suggerimento di @ChrisJohnsen che ha lasciato nei commenti. L'ho trovato utile e volevo trasformarlo in una vera risposta. Chris, se finisci per dare una risposta, eliminerò felicemente questa.
amicitas,

2
Grazie! Anche se a questo manca un passaggio come "git checkout -." come pensa che tutti i file vengano eliminati, giusto?
mrooney,

2
No, purché si utilizzi git clonecome primo comando, non sono necessari ulteriori comandi di checkout. Se invece usi qualcosa del genere git clone --no-checkoutin quel primo passo, dopo che la directory .git viene spostata sarà necessario usare git reset HEADper dire a git che i file non sono stati cancellati.
amicitas

3
Vorrei aggiungere questo come terzo passo: mv temp / .gitignore code / .gitignore
Daniel Aranda,

1
@KalpeshSoni, sì git saprà dei file modificati e sarà possibile vedere le modifiche usando i normali comandi git come git status.
Amicitas,

284

Non clonare, recupera invece. Nel repository:

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

Quindi è possibile ripristinare l'albero per ottenere il commit desiderato:

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

e tu sei come hai clonato.

L'interessante domanda qui (e quella senza risposta): come scoprire su quale commit si basasse il tuo albero nudo, quindi su quale posizione ripristinare.


7
Non sono un fan di questo - per impostazione di github "Suggerimento: l'helper delle credenziali funziona solo quando si clona un URL del repository HTTPS." Stavo usando l'aiutante delle credenziali e questo mi ha mandato in una lunga buca di coniglio abbastanza infruttuosa.
Andrew,

5
'git checkout --track origin / master' funziona bene anche al posto di 'git checkout -b master --track origin / master'. Il reset non è necessario.
felipecrp,

1
Stavo ottenendo l'errore "Errore Git: I seguenti file dell'albero di lavoro non tracciati sarebbero stati sovrascritti dal checkout", quindi ho aggiunto questo comando: git clean -d -fx ""
shakaran

1
sicuramente non consigliabile in tutte le situazioni, ma questo è esattamente ciò di cui avevo bisogno.
Chaim Eliyah,

1
@AndreasKrey La tua risposta originale (che ho visto nella cronologia delle modifiche per vedere) fa esattamente ciò che è necessario per la domanda (e per me). La risposta è cambiata alla cassa senza usare -f, che scarta le modifiche locali ed è esattamente ciò che non voglio. Se fossi in te prenderei in considerazione il ritorno alla tua risposta originale.
Ajean,

77

L'ho fatto per verificare il ramo principale in una directory esistente:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft

2
Questa è un'ottima risposta ed evita il finagling del filesystem.
user151841

1
Questa dovrebbe essere la risposta accettata poiché non è un hack.
php_nub_qq

5
In realtà questo fa esattamente ciò che l'OP (e io) non vogliono, ovvero sovrascrivere le modifiche locali.
Ajean,

Il mio voto indica che ciò mi ha aiutato, non è la migliore risposta alla domanda del PO.
TecBrat,

2
Qualcuno può spiegare perché la -tbandiera viene utilizzata qui?
jfowkes,

38

Vorrei git clonein una nuova directory e copiare il contenuto della directory esistente nel nuovo clone.


4
se lo fai, assicurati di rivedere il diff prima di impegnarti con molta attenzione - questo è un caso assolutamente classico in cui puoi accidentalmente ripristinare le modifiche apportate nel repository di origine da quando hai ricevuto la tua copia di lavoro - perché non ci sono abbastanza informazioni nella copia di lavoro per capire quali sono le modifiche apportate rispetto a com'erano prima di iniziare a apportare modifiche, da unire con altre modifiche apportate nel repository. L'ho visto accadere più volte in questa situazione, al punto in cui ho "fortemente scoraggiato" me stesso e le persone con cui ho lavorato dal farlo mai.
Ben Clifford,

72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpIn altre parole, spostare la .gitdirectory da un clone temporaneo sembra più semplice che ripulire l'albero di lavoro del clone e copiare lì i file esistenti.
Chris Johnsen,

1
@ChrisJohnsen: avresti dovuto trasformarlo in una risposta, questo è sicuramente il modo migliore per farlo imho
Stefano

2
@ChrisJohnsen git mv tmp/.git .ritorna fatal: cannot move directory over file, source=tmp/.git, destination=.gitper me. Qualcuno sa qual è il problema?
Dennis,

6
@Dennis, è un refuso: quel comando dovrebbe essere semplice mv, no git mv; anche se questo non spiega perché hai già un .gitfile (contenente gitdir: some/path/to/a/git-dir, un "gitfile"; se non fosse lì, avresti visto fatal: Not a git repository (or any of the parent directories): .gitinvece).
Chris Johnsen,

34

L'uso di una directory temporanea va bene, ma funzionerà se si desidera evitare questo passaggio. Dalla radice della directory di lavoro:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master

20
git reset --hard origin/masterrimuoverà tutti i file locali.
Mouad Debbar,

1
per aggiungere a ciò che è già stato sottolineato in precedenza, la differenza tra harde mixedè che il misto manterrà le modifiche locali (quindi se in seguito provi a estrarlo ti mostrerà, ad esempio, Impossibile tirare con rebase: hai delle modifiche non messe in scena. Per favore, commettile o nascondile ) , mentre difficile
eliminerà

Hai scritto male il telecomando.
Glenn Dayton,

10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed

7
L'utilizzo git reset --hardannulla le modifiche ai file locali, in particolare NON ciò che questo PO ha richiesto. --mixeddovrebbe essere usato invece.
Caleb,

4

Per clonare un repository git in una directory esistente vuota, procedi come segue:

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

Notare il .alla fine del git clonecomando. Ciò scaricherà il repository nella directory di lavoro corrente.


4
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler,

La directory deve essere vuota.
ok Parla il

4
L'OP chiede come clonare un progetto esistente, affermando che il clone git si lamenta. Cattiva risposta
mix3d

Funziona solo quando crei una nuova directory, esegui i comandi sopra senza usare "git init"
Bilal Ahmed

3

Molte risposte già per farlo nel modo richiesto dal PO. Ma vale la pena notare che farlo al contrario è molto più semplice:

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

Ora hai lo stato desiderato desiderato: clone fresco + modifiche locali.


2

Ci sono due approcci a questo. Ove possibile, vorrei iniziare con una cartella pulita per la nuova directory di lavoro di Git e quindi copiare la versione delle cose in un secondo momento. Questo potrebbe assomigliare a *:

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

A questo punto dovresti avere una copia di lavoro abbastanza pulita con la tua cartella di lavoro precedente come directory di lavoro corrente, quindi qualsiasi modifica include l'eliminazione dei file verrà visualizzata sul radar se esegui git status .

D'altra parte, se davvero devi farlo al contrario, puoi ottenere lo stesso risultato con qualcosa del genere:

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

Ad ogni modo, la prima cosa che vorrei fare è eseguire qualcosa di simile git stash per ottenere una copia di tutte le tue modifiche locali messe da parte, quindi puoi riapplicarle e lavorare su quali vuoi impegnarti.

* Entrambi gli esempi presuppongono che tu inizi sulla shell nella directory principale del tuo progetto.


2

Questo è il migliore di tutti i metodi che ho incontrato

Clonare solo la cartella .git del repository (esclusi i file già presenti existing-dir) in una directory temporanea vuota

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // potrebbe desiderare --no-hardlink per la clonazione del repository locale

Spostare la cartella .git nella directory con i file. Questo rende existing-dirun repository git.

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

Elimina la directory temporanea

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

  2. cd existing-dir

Git pensa che tutti i file vengano eliminati, questo ripristina lo stato del repository su HEAD.

ATTENZIONE: eventuali modifiche locali ai file andranno perse.

  1. git reset --mixed HEAD

1
Un hard reset sembra indesiderato nel 99% dei casi in cui dovresti farlo.
Stefan Fabian,

0

Se stai usando almeno git 1.7.7 (che ha insegnato clonel' --configopzione), per trasformare la directory corrente in una copia funzionante:

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

Questo funziona da:

  • Clonazione del repository in una nuova .gitcartella
  • --mirrortrasforma il nuovo clone in una cartella puramente metadata come .gitdeve essere
  • --config core.bare=falsecontrordini l'implicito bare=truedella --mirrorpossibilità, consentendo in tal modo il repository di avere una directory di lavoro associato e agire come un clone normale

Ciò ovviamente non funzionerà se .gitesiste già una directory di metadati nella directory che si desidera trasformare in una copia funzionante.


1
Nota che questa tecnica comporterà la [core]sezione della configurazione locale includendo sia bare = true e che bare = false . Più problematico è che avrà valori errati per il origintelecomando, con la [remote "origin"]sezione che include mirror = truee una specifica di recupero che non funzionerà correttamente con una copia funzionante. Dopo aver risolto questi problemi, clonare normalmente e spostare la nuova copia di lavoro .gitsarebbe stato più efficiente.
Araxia,

0

Di solito clonerò prima il repository iniziale, quindi sposterò tutto nella cartella esistente nel repository iniziale. Funziona ogni volta.

Il vantaggio di questo metodo è che non ti mancherà nulla del repository iniziale incluso README o .gitignore.

È inoltre possibile utilizzare il comando seguente per completare i passaggi:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo

0

Puoi farlo digitando ricorsivamente le seguenti righe di comando:

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

0

Basta usare il. alla fine del git clonecomando (trovandosi in quella directory), in questo modo:

cd your_dir_to_clone_in/
git clone git@github.com/somerepo/ .

Non funziona: fatale: percorso di destinazione '.' esiste già e non è una directory vuota.
Tristan CHARBONNIER
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.