Comment cloner dans un répertoire non vide?

573

J'ai le répertoire A avec des fichiers correspondant au répertoire B. Le répertoire A peut avoir d'autres fichiers nécessaires. Le répertoire B est un dépôt git.

Je veux cloner le répertoire B dans le répertoire A mais git-clone ne me le permettra pas car le répertoire n'est pas vide.

J'espérais qu'il clonerait juste .git et puisque tous les fichiers correspondent, je pourrais y aller?

Je ne peux pas cloner dans un répertoire vide car j'ai des fichiers dans le répertoire A qui ne sont pas dans le répertoire B et je veux les conserver.

Copier .git n'est pas une option car je veux que les refs poussent / tirent avec et je ne veux pas les configurer manuellement.

Y a-t-il un moyen de faire ça?

Mise à jour: je pense que cela fonctionne, quelqu'un peut-il voir des problèmes? ->

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
la source
5
peut-être pourriez-vous changer la réponse acceptée?
Bastiaan Quast du

Réponses:

724

Cela a fonctionné pour moi:

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

REMARQUE: -t définira la branche en amont pour vous, si c'est ce que vous voulez, et c'est généralement le cas.

cmcginty
la source
70
Cela ne fonctionne pas dans un répertoire non vide lorsque les fichiers entrants existent déjà (comme le décrit la question d'origine). Mais si vous git reset origin/masteraprès git fetch, cela fonctionnera (en préservant également les modifications locales).
Araxia
8
fatal: impossible de mettre à jour les chemins d'accès et de passer en même temps à la branche «maître».
Arnold Roa
7
Cette réponse ne fonctionne pas pour moi. Quand je fais git checkout ...git se plaint que tous mes fichiers seraient écrasés et que je devrais les déplacer en premier. Quand je fais `git reset origin / master /` tout d'abord, la commande checkout se plaint qu'une branche nommée master existe déjà.
Saskia
4
git checkout masterétait une étape finale suffisante pour moi.
yoyo
16
Toutes les étapes ont parfaitement fonctionné , mais le dernier me obtenu: fatal: A branch named 'master' already exists. Je pense que je n'en avais pas vraiment besoin.
Shadi
164

Dans les commandes shell suivantes se existing-dirtrouve un répertoire dont le contenu correspond aux fichiers suivis dans le repo-to-cloneréférentiel 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
la source
5
J'avais besoin de le faire git reset --hard HEADou cela n'abandonnerait pas les fichiers "supprimés".
Dimitar
18
git reset HEADa bien fonctionné pour moi. git reset --hard HEADdétruit tous les changements dans vos fichiers, donc s'ils ne sont pas exactement les mêmes que les fichiers dans le référentiel, vous ne devriez pas le faire.
Tgr
1
git reset HEADne semble pas avoir d'effet sur moi. git reset --hard HEAD- mais cela perd toutes les modifications que vous avez apportées aux fichiers. Y a-t-il une meilleure solution?
Jacob Dorman
1
La réponse de @ Casey - git init / remote add / fetch / checkout - est plus propre et plus simple et ne nécessite aucun dossier temporaire.
yoyo
1
La réponse de @ Casey n'a pas fonctionné pour moi quand il y avait déjà des fichiers dans des dossiers qui devaient rester mais qui n'étaient pas dans le dépôt git. Ceci est utile pour mettre à jour la configuration après avoir exécuté des scripts d'installation où les fichiers et les répertoires sont créés, mais vous devez mettre à jour / ajouter des fichiers au-dessus des éléments installés.
soulston
104

Une légère modification à l'une des réponses qui a fonctionné pour moi:

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

pour commencer immédiatement à travailler sur la branche principale.

mohsaied
la source
1
a dû faire réinitialiser HEAD --hard pour nettoyer le répertoire existant sale, sans supprimer les fichiers non pertinents spécifiés dans gitignore
Ray Foss
1
C'est celui qui a réellement fonctionné pour moi, contrairement à la réponse de @ cmcginty.
certainementake
4
Ce n'est pas tout à fait équivalent à un git-clone - ce qui manque, ce sont les informations en amont de la branche principale. Cela peut être corrigé en ajoutant git branch --set-upstream-to=origin/master master.
Slaven Rezic
Cette version a fonctionné pour moi, il fallait juste faire une réinitialisation git --hard HEAD
Frédéric Klee
29

Avertissement - cela pourrait potentiellement écraser les fichiers.

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

Modifié à partir de la réponse de @ cmcginty - sans le -f, cela n'a pas fonctionné pour moi

JohnFF
la source
Vous devez sûrement extraire tous les fichiers après cela avec git checkout .?
Chris Stryczynski
25

Voici ce que j'ai fini par faire quand j'ai eu le même problème (au moins je pense que c'est le même problème). Je suis allé dans le répertoire A et j'ai couru git init.

Comme je ne voulais pas que les fichiers du répertoire A soient suivis de git, j'ai édité .gitignore et y ai ajouté les fichiers existants. Après cela, j'ai couru git remote add origin '<url>' && git pull origin masteret voíla, B est "cloné" dans A sans un seul hoquet.

BjornSnoen
la source
2
Cette technique ne fonctionne pas dans un répertoire non vide lorsque les fichiers entrants existent déjà (comme le décrit la question d'origine).
Araxia
11

Je l'ai utilisé il y a quelques instants, nécessite les commandes les moins potentiellement destructrices:

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

Et voilá!

KuttKatrea
la source
10

Une autre recette simple semble bien fonctionner pour moi:

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

Mon principal cas d'utilisation pour extraire un répertoire avec des fichiers existants est de contrôler mes fichiers dot Unix avec Git. Sur un nouveau compte, le répertoire personnel contient déjà certains fichiers, peut-être même ceux que je souhaite obtenir de Git.

Ken Williams
la source
1
Les référentiels nus sont configurés un peu différemment et bien que cela fonctionne, je ne le recommanderais pas. :)
ThorSummoner
1
Peux-tu être plus précis? Qu'est-ce qui est différent?
Ken Williams
1
Seulement deux différences: 1.) Le .git/configfichier indique que le référentiel est nu. 2.) Les fichiers normalement stockés dans .gitsont stockés à la racine (que vous avez appelée .git)
mozey
4
Ce sont exactement les changements de clonage .gitet la mise core.bareà falsese prendre en charge, donc je me sens encore bien dans cette méthode.
Ken Williams
10

Cela a fonctionné pour moi:

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

J'ai eu un problème similaire avec un nouveau répertoire Web Apache (compte créé avec WHM) que je prévoyais d'utiliser comme serveur Web intermédiaire. J'avais initialement besoin de cloner mon nouveau projet avec la base de code là-bas et de déployer périodiquement les modifications en tirant du référentiel.

Le problème était que le compte contenait déjà des fichiers de serveur Web comme:

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

... que je ne voulais ni supprimer ni valider mon référentiel. J'avais besoin d'eux pour rester là sans mise en scène et sans suivi.

Ce que j'ai fait:

Je suis allé dans mon dossier Web (dossier_existant):

cd /home/existing_folder

et alors:

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

Il a affiché (comme prévu) une liste de nombreux fichiers non intermédiaires - ceux qui existaient déjà au départ de mon compte Web cPanel.

Ensuite, grâce à cet article , je viens d'ajouter la liste de ces fichiers à:

**.git/info/exclude**

Ce fichier, presque comme le .gitignorefichier, vous permet d'ignorer les fichiers d'être mis en scène. Après cela, je n'avais plus rien à valider dans le répertoire .git / - cela fonctionne comme un.gitignore que personne d'autre ne peut voir.

Vérification des git statusretours:

On branch master
nothing to commit, working tree clean

Maintenant, je peux déployer des modifications sur ce serveur Web en tirant simplement de mon référentiel git. J'espère que cela aidera certains développeurs Web à créer facilement un serveur de transfert.

Vlado
la source
5

Voici ce que je fais:

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

Peut-être que j'ai mal compris votre question, mais ne serait-il pas plus simple si vous copiez / déplacez les fichiers de A vers le git repo B et ajoutez ceux nécessaires avec git add ?

MISE À JOUR: Du git doc:

Le clonage dans un répertoire existant n'est autorisé que si le répertoire est vide.

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

Roberto Aloi
la source
2
Non, le propriétaire et les fichiers peuvent être arbitraires. C'est pour une situation avec plusieurs développeurs. Nous avons tous des répertoires existants et un seul a actuellement une sortie git. Nous avons tous en grande partie le même sous-ensemble de fichiers, nous voulons donc que les autres développeurs puissent cloner tout en conservant leurs fichiers. Et il doit être aussi élégant et pratique que possible.
Dale Forester
Honnêtement, je ne vois pas l'intérêt de se développer dans une telle condition. Vous ne pouvez pas utiliser les branches et les opérations de fusion? Ou avoir des sous-référentiels avec des dépendances externes? Pourquoi voudriez-vous compter sur un seul "git checkout"?
Roberto Aloi
5
Une «caisse simple» n'est pas le but de toute l'épreuve. C'est simplement que c'est ainsi et nous avons besoin d'un moyen d'aller de l'avant. J'ai mis à jour la question d'origine avec une solution qui semble fonctionner. J'apprécie cependant les commentaires.
Dale Forester,
3
Il existe de nombreux cas légitimes pour cela - j'ai une arborescence de dossiers complexe qui doit être configurée AVANT que la source de mon projet puisse être configurée, et cette arborescence de dossiers contient des œuvres sous licence qui ne peuvent pas être stockées sur GitHub par exemple.
BrainSlugs83
3

Je cherchais quelque chose de similaire, et voici ce que j'ai trouvé:

Ma situation est celle où j'ai une arborescence Web active et j'essayais de créer un référentiel distant pour celle-ci sans déplacer aucun des fichiers de l'arborescence Web actuelle. Voici ce que j'ai fait:

  1. Accédez à l'arborescence Web et exécutez git init
  2. Accédez à l'emplacement prévu du référentiel et exécutez: git clone --bare /path/to/web/repo
  3. Modifiez le fichier de configuration dans mon référentiel distant et supprimez la [remote "origin"]section.
  4. Ajoutez une [remote "origin"]section à .git / config dans l'arborescence Web pointant vers le nouveau référentiel distant.
Lendrick
la source
J'aime beaucoup cette recette.
dland
L' git clone --bareici est superflu et détourné. Pourquoi pas seulement git remote add origin <URL>en premier lieu?
Araxia
3

cela fonctionne pour moi , mais vous devez fusionner les fichiers du référentiel distant avec les fichiers locaux:

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

J'ai aimé la réponse de Dale et j'ai également ajouté

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 faible profondeur a évité beaucoup de commits de dev supplémentaires. La nouvelle branche nous a donné une bonne histoire visuelle qu'il y avait du nouveau code de ce serveur qui a été placé dedans. C'est la branche d'utilisation parfaite à mon avis. Merci à la grande perspicacité de toutes les personnes qui ont posté ici.

Dmitri R117
la source
0

J'ai les mêmes problèmes en essayant de cloner en c / code

Mais ce dossier contient tout un tas de projets.

J'ai créé un nouveau dossier dans c / code / newproject et mappé mon clone sur ce dossier.

git for desktop a ensuite demandé à mon utilisateur, puis cloné bien.

À M
la source