Comment convertir un dépôt Git normal en un dépôt nu?

603

Comment puis-je convertir un dépôt Git «normal» en un dépôt nu?

La principale différence semble être:

  • dans le référentiel Git normal, vous avez un .gitdossier à l'intérieur du référentiel contenant toutes les données pertinentes et tous les autres fichiers constituant votre copie de travail

  • dans un référentiel Git nu, il n'y a pas de copie de travail et le dossier (appelons-le repo.git) contient les données réelles du référentiel

Boldewyn
la source
16
Vraisemblablement, c'est une méthode plus courte:mv repo/.git repo.git; rm -rf repo
jameshfisher
Oui c'est vrai. Quand j'ai écrit la question, ce n'était qu'un extrait de mon histoire, que j'ai exécuté l'autre minute.
Boldewyn
54
@eegg Utiliser &&au lieu de ;en cas d' mvéchec!

Réponses:

610

En bref: remplacez le contenu de repopar le contenu de repo/.git, puis dites au référentiel qu'il s'agit désormais d'un référentiel nu.

Pour ce faire, exécutez les commandes suivantes:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Notez que cela est différent de faire un git clone --barevers un nouvel emplacement (voir ci-dessous).

Jörg W Mittag
la source
9
Merci pour l'astuce core.bare. Maintenant, après avoir googlé cette option, je peux la confirmer: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn
14
Je vous remercie! Cela me semble plus propre: mv repo / .git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof
56
C'est tellement plus compliqué et fragile que la réponse ci-dessous ( git clone --bare /path/to/repo).
djd
7
Cette rmcommande peut avoir besoin * \.[!.]*plutôt que *pour supprimer des fichiers dot et des répertoires dot.
minopret
6
@Ciantic: Encore une fois, comme je l'ai déjà expliqué dans mon commentaire ci-dessus, ma réponse a été donnée il y a 3 ans, mais il y a 5 mois, quelqu'un a modifié la question en quelque chose de complètement différent. Aucune des réponses sur cette page fera tout plus de sens. Cette séquence de commandes a été directement copiée de la question, je viens d'ajouter les deux dernières lignes.
Jörg W Mittag
244

Votre méthode semble fonctionner; la structure de fichiers d'un référentiel nu est exactement ce qui se trouve dans le répertoire .git. Mais je ne sais pas si l'un des fichiers est réellement modifié, donc si cela échoue, vous pouvez simplement faire

git clone --bare /path/to/repo

Vous devrez probablement le faire dans un répertoire différent pour éviter un conflit de nom, puis vous pouvez simplement le déplacer là où vous le souhaitez. Et vous devrez peut-être modifier le fichier de configuration pour pointer vers l'emplacement de votre dépôt d'origine.

jonescb
la source
50
Mal, cette méthode n'est pas l'équivalent. Faire un clone ne préserve pas les options de configuration, ce qui peut être essentiel au bon fonctionnement, comme si vous utilisez git-p4. De plus, un clone détruit les télécommandes, encore une fois avec quelque chose comme git-p4, vous perdez la branche p4 / master lorsque vous clonez, donc l'approche ci-dessus est préférable.
nosatalian
26
Mais vous pouvez facilement transférer les options de configuration en copiant les parties respectives du fichier de configuration. Je considérerais toujours cette méthode plus propre que de copier et renommer des fichiers manuellement.
Philipp
6
C'est parfait après une migration de subversion car git-svn ne prend pas en charge --bare.
Keyo
11
Pour éviter le conflit de noms ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja
Cela fonctionne tant que vous exécutez git update-server-infole référentiel nu après la création.
ACK_stoverflow
116

Je pense que le lien suivant serait utile

GitFaq: Comment rendre nu un référentiel non-nu existant?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
xhh
la source
2
Oui, c'est bien ce que j'ai cherché, merci! Cependant, leur deuxième proposition ( git clone) présente les inconvénients que nosatalian a mentionnés ci-dessus.
Boldewyn
1
La documentation que vous avez suggérée continue: "Une méthode plus sûre consiste à laisser Git gérer tous les paramètres internes pour vous en faisant quelque chose comme ça ... git clone --bare -l <path_to_repos> <new_dir>"
dafunker
74

À moins que vous ne vouliez ou n'ayez spécifiquement besoin de tordre des bits sur le système de fichiers, il est vraiment simple de créer une version nue d'un référentiel non nu (mentionné dans plusieurs autres articles ici). Cela fait partie des fonctionnalités de base de git:

git clone --bare existing_repo_path bare_repo_path

Chip Kaye
la source
6
C'est étonnant que la meilleure réponse de loin ait 0 votes après> 4 mois. La «réponse acceptée» pas très bonne mais dangereuse en compte 200!
Stabledog
36
Pas étonnant du tout - cette réponse ne fait pas ce que la question d'origine demandait. Il ne convertit pas un dépôt, il en clone un, perdant ainsi des informations dans le processus (par exemple, les succursales distantes).
GreenAsJade
15

Veuillez également envisager d'utiliser

git clone --mirror path_to_source_repository

De la documentation :

Configurez un miroir du référentiel source. Cela implique - nu. Comparé à --bare, --mirror non seulement mappe les branches locales de la source aux branches locales de la cible, il mappe toutes les références (y compris les branches de suivi à distance, les notes, etc.) et met en place une configuration refspec telle que toutes ces références sont écrasés par une mise à jour à distance git dans le référentiel cible.

Jacek Krawczyk
la source
On dirait que c'est le moyen le plus concis, le plus complet et le plus sûr de faire ce que l'OP veut (contre juste clone). Suis-je en train de manquer quelque chose? C'était --mirrorun ajout relativement récent?
Craig Silver
@CraigSilver: Non, comme je le vois dans l'historique de la documentation sous une telle forme, il --mirrorest disponible à partir de la version 1.7, donc déjà assez long. Vous pouvez vérifier ici
Jacek Krawczyk
7

Je voulais juste pousser vers un référentiel sur un chemin réseau, mais git ne me le permettrait pas à moins que ce référentiel ne soit marqué comme nu. Tout ce dont j'avais besoin était de changer sa configuration:

git config --bool core.bare true

Pas besoin de jouer avec les fichiers, sauf si vous voulez les garder propres.

Slion
la source
3
Cela est dangereux lorsque vous souhaitez également travailler sur l'arborescence de travail du référentiel distant. Il y a de fortes chances que tôt ou tard vous annuliez une modification simplement parce que votre arborescence de travail à distance et votre index n'étaient pas synchronisés avec le référentiel. Je ne recommande pas cette solution, si vous ne savez pas exactement ce que vous faites.
Boldewyn
Certes, vous ne devez pas travailler sur l'arborescence du référentiel nu distant.
Slion
6

j'ai lu les réponses et je l'ai fait:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

cela laissera le contenu repos/.gitcomme à nurepos.git

Dan D.
la source
4

Voici ce que je pense être le plus sûr et le plus simple. Il n'y a rien ici non indiqué ci-dessus. Je veux juste voir une réponse qui montre une procédure étape par étape sûre. Vous démarrez un dossier à partir du référentiel (repo) que vous souhaitez mettre à nu. J'ai adopté la convention impliquée ci-dessus selon laquelle les dossiers de référentiel nus ont une extension .git.

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
sdesciencelover
la source
1
ce n'est pas vraiment plus sûr depuis que vous avez fait votre sauvegarde en utilisant git clone. La sauvegarde par clonage vous fera perdre certaines configurations, ce qui dans certains cas peut être critique pour le référentiel.
Lie Ryan
C'est noté. Les seules configurations dont je me suis jamais soucié sont globales pour tous mes référentiels locaux.
sdesciencelover
4

Lisez simplement

Pro Git Book: 4.2 Git sur le serveur - Obtenir Git sur un serveur

qui se résument à

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Ensuite, placez my_project.git sur le serveur

Ce qui est principalement, quelle réponse # 42 a essayé de souligner. On pourrait à coup sûr réinventer la roue ;-)

apos
la source
Je ne vois pas, ce que cette réponse ajoute, qui n'a pas été discuté de manière arbitraire dans aucune des autres réponses (y compris les votes négatifs). Pourriez-vous clarifier? (Soit dit en passant: le livre Pro Git dit "C'est à peu près équivalent à quelque chose comme ..." , et cette équivalence approximative exacte est également déjà discutée ici.)
Boldewyn
3

Voici une petite fonction BASH que vous pouvez ajouter à votre .bashrc ou .profile sur un système UNIX. Une fois ajouté et le shell est redémarré ou le fichier est rechargé via un appel à source ~/.profileou source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Une fois appelé dans un répertoire contenant un répertoire .git, il apportera les modifications appropriées pour convertir le référentiel. Si aucun répertoire .git n'est présent lors de l'appel, un message FAILURE apparaîtra et aucune modification du système de fichiers ne se produira.

nyteshade
la source
1

Les méthodes qui disent de supprimer des fichiers et de bouger avec le déplacement du répertoire .git ne sont pas propres et n'utilisent pas la méthode "git" pour faire quelque chose qui devrait être simple. C'est la méthode la plus propre que j'ai trouvée pour convertir un dépôt normal en un dépôt nu.

Premier clone / chemin / vers / normal / repo dans un référentiel nu appelé repo.git

git clone --bare /path/to/normal/repo

Supprimez ensuite l'origine qui pointe vers / chemin / vers / normal / repo

cd repo.git
git remote rm origin

Enfin, vous pouvez supprimer votre dépôt d'origine. Vous pouvez renommer repo.git en repo à ce stade, mais la convention standard pour signifier un référentiel git est quelque chose.git, donc je le laisserais personnellement de cette façon.

Une fois que vous avez fait tout cela, vous pouvez cloner votre nouveau référentiel nu (ce qui crée en fait un référentiel normal, et est également la façon dont vous le convertiriez de nu en normal)

Bien sûr, si vous avez d'autres amonts, vous voudrez en prendre note et mettre à jour votre référentiel nu pour l'inclure. Mais encore une fois, tout cela peut être fait avec la commande git. N'oubliez pas que les pages de manuel sont votre ami.

krux
la source
1
Avez-vous pris la peine de lire les autres réponses? Surtout les commentaires de @ jonescb et @ nosatalian? La méthode "git" est la suivante: "Faites autant que possible avec des fichiers texte". Vous devriez commencer à enquêter sur les éléments internes d'un .gitdossier. C'est très instructif d'apprendre, comment les pièces s'assemblent.
Boldewyn
1

Dans le cas où vous avez un référentiel avec quelques branches / références / têtes / * locales et quelques branches distantes distantes / origine / * ET si vous voulez le convertir en un référentiel BARE avec toutes les branches dans / refs / têtes / *

vous pouvez effectuer les opérations suivantes pour enregistrer l'historique.

  1. créer un référentiel nu
  2. cd dans le référentiel local qui a des succursales locales et des succursales distantes
  3. git push / path / to / bare / repo + refs / remotes / origin / : refs / heads /
Senthil A Kumar
la source
0

J'ai utilisé le script suivant pour lire un fichier texte qui contient une liste de tous mes dépôts SVN et les convertir en GIT, puis utiliser git clone --bare pour convertir en un dépôt git nu

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt a le format

repo1_name
repo2_name

et users.txt a le format

(no author) = Prince Rogers <[email protected]>

www-data est l'utilisateur du serveur Web Apache, une autorisation est nécessaire pour pousser les modifications via HTTP

Pedro Vicente
la source
0

Voici la définition d'un dépôt nu de gitglossary :

Un référentiel nu est normalement un répertoire correctement nommé avec un suffixe .git qui n'a pas de copie extraite localement des fichiers sous contrôle de révision. Autrement dit, tous les fichiers d'administration et de contrôle de Git qui seraient normalement présents dans le sous-répertoire caché .git sont directement présents dans le répertoire repository.git à la place, et aucun autre fichier n'est présent et extrait. Habituellement, les éditeurs de référentiels publics mettent à disposition des référentiels nus.

Je suis arrivé ici parce que je jouais avec un "dépôt local" et je voulais pouvoir faire ce que je voulais comme s'il s'agissait d'un dépôt distant. Je jouais juste, essayant d'en apprendre plus sur Git. Je suppose que c'est la situation pour quiconque veut lire cette réponse.

J'aimerais d'avis d'experts ou des contre-exemples, mais il semble que (après en fouillant dans un code source git que j'ai trouvé) tout simplement aller au fichier spécifique .git/configet le réglage du noyau attribut nu à vrai , git vous permettra de faire tout que vous souhaitez effectuer à distance sur le référentiel. C'est-à-dire que les lignes suivantes doivent exister dans .git/config:

[core]
    ...
    bare = true
...

(C'est à peu près ce que git config --bool core.bare truefera la commande , ce qui est probablement recommandé pour faire face à des situations plus compliquées)

Ma justification de cette affirmation est que, dans le code source de git, il semble y avoir deux façons différentes de tester si un dépôt est nu ou non. L'une consiste à vérifier une variable globale is_bare_repository_cfg. Ce paramètre est défini lors d'une phase de configuration de l'exécution et reflète la valeur trouvée dans le .git/configfichier. L'autre est une fonction is_bare_repository(). Voici la définition de cette fonction:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

Je n'ai pas le temps ni l'expertise pour le dire avec une confiance absolue, mais pour autant que je sache si vous avez baredéfini l' attribut truedans .git/config, cela devrait toujours revenir 1. Le reste de la fonction concerne probablement la situation suivante:

  1. core.bare n'est pas défini (c'est-à-dire ni vrai ni faux)
  2. Il n'y a pas d'arbre de travail (c'est-à-dire que le sous-répertoire .git est le répertoire principal)

Je l'expérimenterai quand je le pourrai plus tard, mais cela semblerait indiquer que la définition de core.bare = true équivaut à supprimer core.bare du fichier de configuration et à configurer correctement les répertoires.

Quoi qu'il en soit, la définition de core.bare = true vous permettra certainement de pousser, mais je ne suis pas sûr si la présence de fichiers de projet entraînera le dysfonctionnement d'autres opérations. C'est intéressant et je suppose instructif de pousser vers le référentiel et de voir ce qui s'est passé localement (c'est-à-dire exécuter git statuset donner un sens aux résultats).

Nathan Chappell
la source
-1

Tout d'abord, backupvotre référentiel existant:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Ensuite, exécutez ce qui suit:

git clone --bare -l non_bare_repo new_bare_repo
Shaks
la source
À quoi sert le clone intermédiaire?
Stabledog
-4

Oneliner pour effectuer toutes les opérations ci-dessus:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(ne me blâmez pas si quelque chose explose et que vous n'avez pas eu de sauvegarde: P)

Tarmo
la source
-9

Wow, c'est tout simplement incroyable de voir combien de personnes sont intervenues à ce sujet, d'autant plus qu'il ne semble pas qu'un seul s'est arrêté pour demander pourquoi cette personne fait ce qu'il fait.

La SEULE différence entre un dépôt git nu et non nu est que la version non nue a une copie de travail. La principale raison pour laquelle vous auriez besoin d'un dépôt nu est que si vous vouliez le mettre à la disposition d'un tiers, vous ne pouvez pas réellement y travailler directement, donc à un moment donné, vous devrez le cloner à quel moment vous êtes de retour à une version de travail régulière.

Cela étant dit, pour se convertir à un repo nu, tout ce que vous avez à faire est de vous assurer que vous n'avez aucun commit en attente, puis juste:

rm -R * && mv .git/* . && rm -R .git

Voilà, repo nu.

Justin Buser
la source
11
Cela ne le rendra pas assez nu. Essayez de pousser dedans. Vous devez faire git config core.bare truede même.
Antony Hatchkins
Je n'ai pas downvote, mais je voulais juste souligner que la 1ère partie de cette réponse qui explique pourquoi vous voudriez un repo nu vs un non repo est ok , bien qu'il ne contienne pas assez de détails techniques, et peut être légèrement imprécis. Cependant , pour la 2e partie de votre réponse, alors que ces commandes configurent votre dépôt pour être nu, Anthony a raison , vous devez toujours le définir git config core.bare true, tout comme dans cette réponse .