web-dev-qa-db-fra.com

Comment convertir un référentiel Git nu en un référentiel normal (en place)?

J'ai un référentiel Git nu, mais je dois accéder à son contenu et le parcourir via ssh (dans un gestionnaire de fichiers comme celui de l'utilisateur).

Je suppose que je pourrais le cloner:

git clone -l <path_to_bare_repo> <new_normal_repo>

Cependant, mon référentiel a une taille d’environ 20 Go et je n’ai pas l’espace pour le dupliquer. Existe-t-il un moyen de convertir le référentiel nu en place pour en faire une copie de travail?

64
nyi

Note: J'ai testé cela sur un référentiel très simple 1-commit. Vérifiez cette information, lisez les pages de manuel , et soyez toujours heureux d'avoir sauvegardé vos données avant de suivre les conseils que vous avez trouvés sur StackOverflow. (Vous sauvegardez, non?)

Pour convertir un référentiel --bare en un référentiel non-nu:

  1. Créez un dossier .git dans le niveau supérieur de votre référentiel. 
  2. Déplacez les éléments de gestion du référentiel (HEAD branches config description hooks info objects refs etc.) dans le .git que vous venez de créer. 
  3. Exécutez git config --local --bool core.bare false pour convertir le référentiel git local en non-nu. 
  4. (via un commentaire de Tamás Pap ) Après l'étape 3, vous verrez que vous êtes sur une branche master (ou quelle que soit votre branche principale) et que tous vos fichiers sont supprimés et que la suppression est effectuée. C'est normal. Procédez simplement à la vérification master ou faites un git reset --hard et vous avez terminé.
  5. (pour résoudre le problème signalé par Royi ) Modifiez le fichier .git/config en ajoutant la ligne fetch = +refs/heads/*:refs/remotes/Origin/* après le url = <...> dans la section [remote "Origin"]. Sinon, git fetch ne verra pas Origin/master et les autres branches d'Origin.

Ces étapes vont dans le sens opposé à cette question , "git-convert normal to référentiel nu" - en particulier, notez cette réponse , qui indique que les étapes ci-dessus (dans, je présume , soit dans les deux sens) est différent de faire un git-clone. Je ne sais pas si cela vous concerne, mais vous avez mentionné git clone dans la question. 

90
simont

J'ai eu un scénario légèrement différent:

Solution:

  • cloner un repo nu dans ce contenu, dans un répertoire .git:
    git clone --bare https://github.com/user/project .git
  • Marquez-le comme un rapport non nu:
    git config --local --bool core.bare false
  • réinitialiser l'index (sinon, tout est supposé avoir été supprimé, car un référentiel .gitbare n'inclut pas le fichier 'index'.)
    git reset HEAD -- .
    Cela restaure le .git/index.

J'ai effectivement transformé un rapport nu en un stock non nu, tout en préservant le contenu que j'avais précédemment obtenu.
Le script complet que j'utilise depuis des années comprend les étapes suivantes:

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.Origin.fetch +refs/heads/*:refs/remotes/Origin/*
git fetch Origin
git branch -u Origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

Mais je reconnais que la solution acceptée (avec le utile git reset étape ajoutée par ADTC ) est plus simple. 

15
VonC

Pour simplifier et combiner les informations dans les réponses:

Il existe deux différences qui différencient un rapport nu d'un dossier .git normal:

  • core.bare est défini sur true dans le fichier de configuration
  • le fichier d'index et l'arbre de travail n'existent pas

Donc, vous pouvez simplement déplacer votre rapport nu pour être le sous-dossier .git d’un nouveau dossier,

mkdir clone
mv bare.git clone/.git

Changer core.bare:

cd clone
git config --local --bool core.bare false

Et générez le fichier d'index et l'arbre de travail:

git checkout master

Je recommande git checkout plutôt que git reset pour générer les fichiers, au cas où il serait accidentellement saisi au mauvais endroit.

9
fuzzyTew

Si vous manquez d'espace disque, le développement de l'arborescence de travail en le convertissant en un référentiel normal posera un problème, mais vous pouvez parcourir le contenu d'un référentiel nu sans le convertir. Utilisez git cat-file -p <commit-sha> sur n’importe quel commit pour voir l’arbre auquel il fait référence. Utilisez git cat-file -p <blob-sha> pour voir le contenu du fichier référencé par le blob. Utilisez git show <sha>:path où sha est soit un commit, soit un arbre pour voir le contenu du blob dans le chemin. 

6
William Pursell

La question de l'affiche originale est de ne pas avoir assez d'espace pour faire les choses de manière simple. Pour ceux qui ont assez d’espace, la réponse est beaucoup plus simple:

git clone foo.git foo
5
sarnold

Si cela ne vous dérange pas de travailler sur différents arbres de travail, alors

git worktree add ../repo2
cd ..
git status # now works fine

S'il vous plaît noter que ce n'est pas un clone.

1
Boaz Nahum

cd en repo nu et faire 

git config core.bare false

git reset --hard

ou 

git clone X.git X (vous donnera un repo git régulier nommé X) 

0
nPcomp

Push-to-Deploy

Plutôt que de convertir la télécommande nue en un référentiel standard, vous pouvez utiliser le script de post-réception dans le répertoire des hooks pour développer le référentiel dans un répertoire de déploiement.

Voici un bon exemple d'installation du service Push-to-Deploy

Pour plus de facilité, voici l’exemple du contenu du script tiré du lien ci-dessus. Il déploiera uniquement les transferts depuis la branche "master" vers un répertoire nommé "deploy" situé au même niveau que le répertoire parent du référentiel:

#!/usr/bin/env Ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
0
Isaac Brown