Come posso clonare in una directory non vuota?


573

Ho la directory A con i file corrispondenti alla directory B. La directory A potrebbe avere altri file necessari. La directory B è un repository git.

Voglio clonare la directory B nella directory A ma git-clone non me lo permetterà poiché la directory non è vuota.

Speravo solo che clonasse .git e dato che tutti i file corrispondono potrei andare da lì?

Non riesco a clonare in una directory vuota perché ho file nella directory A che non si trovano nella directory B e voglio conservarli.

Copiare .git non è un'opzione poiché voglio che i ref facciano push / pull e non li voglio impostare manualmente.

C'è un modo per fare questo?

Aggiornamento: penso che funzioni, qualcuno può vedere qualche 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

5
potresti cambiare la risposta accettata?
Bastiaan Quast,

Risposte:


724

Questo ha funzionato per me:

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 imposterà il ramo upstream per te, se è quello che vuoi, e di solito lo è.


70
Questo non funziona in una directory non vuota quando i file in arrivo esistono già (come descritto nella domanda originale). Ma se git reset origin/masterdopo git fetch, funzionerà (preservando anche eventuali modifiche locali).
Araxia,

8
fatale: impossibile aggiornare i percorsi e passare contemporaneamente al ramo "master".
Arnold Roa,

7
Questa risposta non funziona per me. Quando lo faccio, mi git checkout ...lamento che tutti i miei file verrebbero sovrascritti e dovrei prima spostarli. Quando faccio `git reset origin / master /` prima il comando di checkout si lamenta che esiste già un ramo chiamato master.
Saskia,

4
git checkout masterè stato un passaggio finale sufficiente per me.
yoyo

16
Tutte le fasi ha funzionato perfettamente, ma l'ultimo mi ha fatto: fatal: A branch named 'master' already exists. Penso di non averne davvero bisogno.
Shadi,

164

Nei seguenti comandi shell existing-dirè una directory il cui contenuto corrisponde ai file tracciati nel repo-to-clonerepository 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

5
Dovevo farlo git reset --hard HEADo non si arrendeva ai file "cancellati".
Dimitar,

18
git reset HEADha funzionato bene per me. git reset --hard HEADdistrugge eventuali modifiche ai tuoi file, quindi se non sono esattamente gli stessi dei file nel repository, non dovresti farlo.
Tgr

1
git reset HEADnon sembra avere alcun effetto per me. git reset --hard HEADsì, ma questo perde qualsiasi modifica apportata ai file. C'è una soluzione migliore?
Jacob Dorman,

1
La risposta di @ Casey - git init / remote remote / fetch / checkout - è più semplice e pulita e non richiede cartelle temporanee.
yoyo

1
La risposta di @ Casey non ha funzionato per me quando c'erano già file nelle cartelle che dovevano rimanere ma che non erano nel repository git. Ciò è utile per aggiornare la configurazione dopo aver eseguito gli script di installazione in cui vengono creati file e directory ma è necessario aggiornare / aggiungere file sopra gli elementi installati.
soulston,

104

Una leggera modifica a una delle risposte che ha funzionato per me:

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

per iniziare subito a lavorare sul ramo principale.


1
ho dovuto resettare HEAD --hard per pulire la directory esistente sporca, senza rimuovere i file irrilevanti specificati in gitignore
Ray Foss

1
Questo è quello che ha funzionato per me, al contrario della risposta di @ cmcginty.
sicuramente il

4
Questo non è del tutto equivalente a un clone git - ciò che manca sono le informazioni a monte per il ramo master. Questo può essere risolto aggiungendo git branch --set-upstream-to=origin/master master.
Slaven Rezic,

Questa versione ha funzionato per me, ho dovuto solo eseguire un reset git --hard HEAD
Frédéric Klee

29

Avviso: questo potrebbe potenzialmente sovrascrivere i file.

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

Modificato dalla risposta di @ cmcginty - senza il -f non ha funzionato per me


Sicuramente devi controllare tutti i file dopo questo con git checkout .?
Chris Stryczynski,

25

Ecco cosa ho fatto quando ho avuto lo stesso problema (almeno penso che sia lo stesso problema). Entrai nella directory A e corsigit init .

Dato che non volevo che i file nella directory A fossero seguiti da git, ho modificato .gitignore e vi ho aggiunto i file esistenti. Dopo questo ho corso git remote add origin '<url>' && git pull origin masteret voíla, B è "clonato" in A senza un singolo singhiozzo.


2
Questa tecnica non funziona in una directory non vuota quando i file in arrivo esistono già (come descritto nella domanda originale).
Araxia,

11

L'ho usato qualche istante fa, richiede i comandi meno potenzialmente distruttivi:

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á!


10

Un'altra semplice ricetta sembra funzionare bene per me:

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

Il mio caso d'uso principale per il checkout in una directory con file esistenti è controllare i miei dotfile Unix con Git. Su un nuovo account, la directory home avrà già alcuni file, forse anche quelli che voglio ottenere da Git.


1
I repository nudi sono impostati in modo leggermente diverso e, mentre funziona, non lo consiglierei. :)
ThorSummoner,

1
Può essere più preciso? Ciò che è diverso?
Ken Williams,

1
Solo due differenze: 1.) Il .git/configfile indica che il repository è nudo. 2.) I file normalmente archiviati .gitvengono archiviati nella radice (che hai chiamato .git)
mozey,

4
Questi sono esattamente i cambiamenti che la clonazione di .gite impostazione core.baredi falsesi prenderà cura di, quindi mi sento ancora bene con questo metodo.
Ken Williams,

10

Questo ha funzionato per me:

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

6

Ho avuto un problema simile con una nuova directory Web Apache (account creato con WHM) che avevo pianificato di utilizzare come server Web di gestione temporanea. Inizialmente dovevo clonare il mio nuovo progetto con la base di codice e distribuire periodicamente le modifiche estraendole dal repository.

Il problema era che l'account conteneva già file del server Web come:

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

... che non volevo cancellare o impegnare nel mio repository. Avevo bisogno che restassero lì non organizzati e non monitorati.

Cosa ho fatto:

Sono andato alla mia cartella web (cartella_esistente):

cd /home/existing_folder

e poi:

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

Ha visualizzato (come previsto) un elenco di molti file non messi in scena - quelli che esistevano già inizialmente dal mio account web cPanel.

Quindi, grazie a questo articolo , ho appena aggiunto l'elenco di quei file a:

**.git/info/exclude**

Questo file, quasi come il .gitignorefile, consente di ignorare la messa in scena dei file. Dopo questo non ho avuto nulla da impegnare nella directory .git / - funziona come un personale.gitignore che nessun altro può vedere.

Ora controlla i git statusritorni:

On branch master
nothing to commit, working tree clean

Ora posso distribuire le modifiche a questo server Web semplicemente estraendo dal mio repository git. Spero che questo aiuti alcuni sviluppatori Web a creare facilmente un server di gestione temporanea.


5

Ecco cosa sto facendo:

git clone repo /tmp/folder
cp -rf /tmp/folder/.git /dest/folder/
cd /dest/folder
git checkout -f master

4

Forse ho frainteso la tua domanda, ma non sarebbe più semplice copiare / spostare i file da A al repository git B e aggiungere quelli necessari con git add ?

AGGIORNAMENTO: Dal documento git:

La clonazione in una directory esistente è consentita solo se la directory è vuota.

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


2
No, il proprietario e i file potrebbero essere arbitrari. Questo è per una situazione con più sviluppatori. Tutti abbiamo directory esistenti e solo una ha attualmente un checkout git. Tutti abbiamo in gran parte lo stesso sottoinsieme di file, quindi vogliamo che gli altri sviluppatori siano in grado di clonare mantenendo i loro file. E dovrebbe essere il più elegante e conveniente possibile.
Dale Forester

Onestamente, non vedo il punto di svilupparsi in una tale condizione. Non puoi usare le filiali e unire le operazioni? O hai dei repository con dipendenze esterne? Perché vorresti fare affidamento su un singolo "checkout git"?
Roberto Aloi,

5
Un "checkout single git" non è il punto dell'intero calvario. È solo che è così e abbiamo bisogno di un modo per andare avanti. Ho aggiornato la domanda originale con una soluzione che sembra funzionare. Apprezzo il feedback, però.
Dale Forester

3
Ci sono molti casi legittimi per questo - ho un albero di cartelle complesso che deve essere impostato PRIMA di poter configurare l'origine del mio progetto e quell'albero di cartelle contiene lavori su licenza che non possono essere archiviati su GitHub, ad esempio.
BrainSlugs83,

3

Stavo cercando qualcosa di simile, ed ecco cosa mi è venuto in mente:

La mia situazione è quella in cui ho un albero web attivo e stavo cercando di creare un repository remoto per esso senza spostare alcun file nell'albero web corrente. Ecco cosa ho fatto:

  1. Vai all'albero web ed esegui git init
  2. Vai alla posizione prevista del repository ed esegui: git clone --bare /path/to/web/repo
  3. Modifica il file di configurazione nel mio repository remoto e rimuovi la [remote "origin"]sezione.
  4. Aggiungi una [remote "origin"]sezione a .git / config nella struttura web che punta al nuovo repository remoto.

Mi piace molto questa ricetta.
dland

Il git clone --barequi è superfluo e tortuoso. Perché non solo git remote add origin <URL>in primo luogo?
Araxia,

3

questo funziona per me , ma dovresti unire i file del repository remoto con i file locali:

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

1

Mi è piaciuta la risposta di Dale e ho anche aggiunto

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

La profondità ridotta ha evitato molti impegni aggiuntivi da parte degli sviluppatori. Il nuovo ramo ci ha dato una buona storia visiva che c'era un nuovo codice da questo server che è stato inserito. Questo è il ramo uso perfetto secondo me. I miei ringraziamenti per la grande intuizione di tutte le persone che hanno pubblicato qui.


0

Ho avuto gli stessi problemi quando provavo a clonare in c / code

Ma questa cartella contiene un sacco di progetti.

Ho creato una nuova cartella in c / code / newproject e ho mappato il mio clone su questa cartella.

git per desktop ha quindi chiesto al mio utente e poi clonato bene.

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.