Quelle est la meilleure pratique pour «git cloner» dans un dossier existant?

480

J'ai une copie de travail du projet, sans aucune métadonnée de contrôle de source. Maintenant, je voudrais faire l'équivalent de git-clone dans ce dossier et conserver mes modifications locales.

git-clone ne me permet pas de cloner dans un dossier existant. Quelle est la meilleure pratique ici?

ripper234
la source
4
Une meilleure discussion est ici .
cdunn2001
1
@MEM J'aime plus cette réponse, mais ça marche ... stackoverflow.com/a/5377989/11236
ripper234
2
@ ripper234 - Oui. J'étais dans la même situation et je viens de faire ces étapes, et aucun problème. Tout est propre et agréable. Je suppose que c'est une question de préférence, l'essentiel étant que les deux fonctionnent, comme vous le dites. À votre santé.
MEM
1
C'est tellement fou qu'il n'y a pas de moyen propre de le réaliser, si utile lorsque vous voulez cloner un projet dans un dossier partagé monté.
Thomas Decaux le
1
Copie possible de Comment cloner dans un répertoire non vide?
Tobias Kienzler

Réponses:

559

Cela peut être fait en clonant vers un nouveau répertoire, puis en déplaçant le .gitrépertoire dans votre répertoire existant.

Si votre répertoire existant est nommé "code".

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

Cela peut également être fait sans effectuer de vérification lors de la commande clone; plus d'informations peuvent être trouvées ici .

amicitas
la source
25
Notez que c'est exactement la suggestion de @ChrisJohnsen qu'il a laissée dans les commentaires. Je l'ai trouvé utile et je voulais en faire une réponse réelle. Chris, si vous finissez par mettre une réponse, je supprimerai volontiers celle-ci.
amicitas
2
Merci! Bien qu'il manque une étape comme "git checkout -." car il pense que tous les fichiers sont supprimés, non?
mrooney
2
Non, tant que vous utilisez git clonela première commande, aucune autre commande d'extraction n'est nécessaire. Si vous utilisez plutôt quelque chose comme git clone --no-checkoutdans cette première étape, après le déplacement du répertoire .git, il sera nécessaire d'utiliser git reset HEADpour dire à git que les fichiers n'ont pas été supprimés.
amicitas
3
J'ajouterais ceci comme troisième étape: mv temp / .gitignore code / .gitignore
Daniel Aranda
1
@KalpeshSoni, oui git connaîtra les fichiers modifiés et il sera possible de voir les changements en utilisant les commandes git normales telles que git status.
amicitas
284

Ne clonez pas, récupérez à la place. Dans le repo:

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

Ensuite, vous pouvez réinitialiser l'arborescence pour obtenir le commit que vous souhaitez:

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

et vous êtes comme vous avez cloné.

La question intéressante ici (et celle sans réponse): Comment savoir sur quel commit votre arbre nu était basé, d'où la position dans laquelle réinitialiser.

Andreas Krey
la source
7
Je ne suis pas fan de cela - par configuration github "Astuce: l'assistant d'informations d'identification ne fonctionne que lorsque vous clonez une URL de référentiel HTTPS." J'utilisais un assistant d'identification et cela m'a envoyé dans un long trou de lapin assez stérile.
Andrew
5
'git checkout --track origin / master' fonctionne également bien au lieu de 'git checkout -b master --track origin / master'. La réinitialisation n'est pas nécessaire.
felipecrp
1
J'obtenais l'erreur "Erreur Git: les fichiers d'arborescence de travail non suivis suivants seraient remplacés par la caisse", alors j'ajoute cette commande: git clean -d -fx ""
shakaran
1
certainement pas conseillé dans toutes les situations, mais c'est exactement ce dont j'avais besoin.
Chaim Eliyah
1
@AndreasKrey Votre réponse d'origine (que j'ai consultée dans l'historique des modifications) fait exactement ce dont la question (et moi) a besoin. La réponse modifiée barfs à la caisse sans utiliser -f, ce qui annule les modifications locales et est exactement ce que je ne veux pas . Si j'étais vous, je songerais à revenir à votre réponse originale.
Ajean
77

Ce que j'ai fait pour extraire la branche principale dans un répertoire existant:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft
alexwenzel
la source
2
Ceci est une excellente réponse et évite toute manipulation de système de fichiers.
user151841
1
Cela devrait être la réponse acceptée car ce n'est pas un hack.
php_nub_qq
5
En fait, cela fait exactement ce que l'OP (et moi) ne veut pas , c'est d'écraser les changements locaux.
Ajean
Mon vote positif indique que cela m'a aidé, pas que ce soit la meilleure réponse à la question du PO.
TecBrat
2
Quelqu'un peut-il expliquer pourquoi le -tdrapeau est utilisé ici?
jfowkes
38

Je voudrais git clonedans un nouveau répertoire et copier le contenu du répertoire existant dans le nouveau clone.

jhwist
la source
4
si vous faites cela, assurez-vous de revoir le diff avant de vous engager très attentivement - il s'agit d'un cas classique absolu où vous pouvez accidentellement annuler les modifications apportées au référentiel source depuis chaque fois que vous avez obtenu votre copie de travail - car il n'y a pas assez d'informations dans la copie de travail pour déterminer quelles sont les modifications que vous avez apportées par rapport à ce qu'elles étaient avant de commencer à apporter des modifications, pour les fusionner avec d'autres modifications apportées dans le référentiel. J'ai vu cela se produire maintes et maintes fois dans cette situation, au point que je me suis «fortement découragé» et les gens avec qui j'ai travaillé de ne jamais le faire.
Ben Clifford
72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpEn d'autres termes, déplacer le .gitrépertoire d'un clone temporaire semble plus simple que de nettoyer l'arborescence de travail du clone et d'y copier les fichiers existants.
Chris Johnsen
1
@ChrisJohnsen: vous auriez dû en faire une réponse, c'est certainement la meilleure façon de le faire à mon humble avis
Stefano
2
@ChrisJohnsen git mv tmp/.git .revient fatal: cannot move directory over file, source=tmp/.git, destination=.gitpour moi. Quelqu'un sait-il quel est le problème?
Dennis
6
@Dennis, C'est une faute de frappe: cette commande doit être simple mv, non git mv; bien que cela n'explique pas pourquoi vous avez .gitdéjà un fichier (contenant gitdir: some/path/to/a/git-dirun «gitfile»; s'il n'était pas là, alors vous l'auriez vu à la fatal: Not a git repository (or any of the parent directories): .gitplace).
Chris Johnsen
34

L'utilisation d'un répertoire temporaire est très bien, mais cela fonctionnera si vous voulez éviter cette étape. Depuis la racine de votre répertoire de travail:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master
user1055643
la source
20
git reset --hard origin/mastersupprimera tous les fichiers locaux.
Mouad Debbar
1
à ajouter à ce qui a déjà indiqué ci - dessus, la différence entre hardet mixedest que mixte gardera les changements locaux (donc si vous essayez plus tard de tirer ça va vous montrer par exemple ne peut pas tirer avec rebasage. Vous avez des changements Unstaged S'il vous plaît engager ou les cacher ) , tandis que le dur
rejettera
Vous avez mal orthographié à distance.
Glenn Dayton
10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed
return1.at
la source
7
L'utilisation git reset --hardnuke les modifications du fichier local, en particulier PAS ce que ce PO a demandé. --mixeddevrait être utilisé à la place.
Caleb
4

Pour cloner un dépôt git dans un répertoire existant vide, procédez comme suit:

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

Remarquez le .à la fin de votre git clonecommande. Cela va télécharger le dépôt dans le répertoire de travail actuel.

Ok parle
la source
4
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler
Le répertoire doit être vide.
okTalk
4
L'OP demande comment cloner dans un projet existant, déclarant que git clone se plaint. Mauvaise réponse.
mix3d
Cela ne fonctionne que lorsque vous créez un nouveau répertoire, exécutez les commandes ci-dessus sans utiliser "git init"
Bilal Ahmed
3

Beaucoup de réponses déjà pour le faire de la manière demandée par le PO. Mais il convient de noter que le faire dans le sens inverse est beaucoup plus simple:

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

Vous avez maintenant l'état cible souhaité - nouveau clone + changements locaux.

Andrew
la source
2

Il y a deux approches à cela. Dans la mesure du possible, je commencerais par un dossier propre pour votre nouveau répertoire de travail git, puis je copierais votre version des choses plus tard. Cela pourrait ressembler à quelque chose comme *:

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

À ce stade, vous devriez avoir une copie de travail assez propre avec votre dossier de travail précédent en tant que répertoire de travail actuel afin que toutes les modifications incluent des suppressions de fichiers apparaîtront sur le radar si vous exécutez git status .

D'un autre côté, si vous devez vraiment le faire dans l'autre sens, vous pouvez obtenir le même résultat avec quelque chose comme ceci:

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

Quoi qu'il en soit, la première chose que je ferais serait d'exécuter quelque chose comme git stash pour obtenir une copie de toutes vos modifications locales mises de côté, puis vous pouvez les réappliquer et déterminer celles que vous souhaitez engager.

* Les deux exemples supposent que vous démarrez sur le shell dans le répertoire parent de votre projet.

Caleb
la source
2

C'est la meilleure de toutes les méthodes que j'ai rencontrées

Clonez uniquement le dossier .git du référentiel (à l'exclusion des fichiers car ils se trouvent déjà existing-dir) dans un répertoire temporaire vide

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // pourrait vouloir --no-hardlinks pour cloner le dépôt local

Déplacez le dossier .git vers le répertoire contenant les fichiers. Cela fait existing-dirun dépôt git.

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

Supprimer le répertoire temporaire

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

  2. cd existing-dir

Git pense que tous les fichiers sont supprimés, cela ramène l'état du dépôt à HEAD.

AVERTISSEMENT: toutes les modifications locales apportées aux fichiers seront perdues.

  1. git reset --mixed HEAD
Amirtha Rajan
la source
1
Une réinitialisation matérielle semble indésirable dans 99% des cas où vous auriez besoin de le faire.
Stefan Fabian
0

Si vous utilisez au moins git 1.7.7 (qui a enseigné clonel' --configoption), pour transformer le répertoire actuel en une copie de travail:

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

Cela fonctionne par:

  • Clonage du référentiel dans un nouveau .gitdossier
  • --mirrortransforme le nouveau clone en un dossier de métadonnées purement comme il .gitdoit être
  • --config core.bare=falsecontrecarre l'implicite bare=truede l' --mirroroption, permettant ainsi au référentiel d'avoir un répertoire de travail associé et d'agir comme un clone normal

Cela ne fonctionnera évidemment pas si un .gitrépertoire de métadonnées existe déjà dans le répertoire que vous souhaitez transformer en copie de travail.

ThorSummoner
la source
1
Notez que cette technique entraînera la [core] section de la configuration locale comprenant à la fois bare = true et bare = false . Plus problématique est qu'elle aura les mauvaises valeurs pour la origintélécommande, avec la [remote "origin"]section incluant mirror = trueet une spécification de récupération qui ne fonctionnera pas correctement avec une copie de travail. Après avoir résolu ces problèmes, le clonage normal et le déplacement des nouvelles copies de travail .gitauront été plus efficaces.
Araxia
0

Habituellement, je clone d'abord le référentiel initial, puis je déplace tout le contenu du dossier existant vers le référentiel initial. Ça marche à chaque fois.

L'avantage de cette méthode est que vous ne manquerez rien du référentiel initial, y compris README ou .gitignore.

Vous pouvez également utiliser la commande ci-dessous pour terminer les étapes:

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

Vous pouvez le faire en tapant récursivement les lignes de commande suivantes:

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
la source
0

Utilisez simplement le. à la fin de la git clonecommande (se trouvant dans ce répertoire), comme ceci:

cd your_dir_to_clone_in/
git clone [email protected]/somerepo/ .
John F
la source
Ne fonctionne pas: fatal: chemin de destination '.' existe déjà et n'est pas un répertoire vide.
Tristan CHARBONNIER