Quelle est la différence - pratique - entre un référentiel nu et non référentiel?

213

J'ai lu sur les référentiels nus et non nus / par défaut dans Git. Je n'ai pas été en mesure de bien comprendre (théoriquement) les différences entre eux, et pourquoi je devrais "pousser" vers un référentiel nu. Voici l'affaire:

Actuellement, je suis le seul à travailler sur un projet sur 3 ordinateurs différents, mais il y aura plus de personnes impliquées plus tard, donc j'utilise Git pour le contrôle de version. Je clone le référentiel nu sur tous les ordinateurs, et lorsque je termine mes modifications sur l'un d'entre eux, je valide et pousse les modifications apportées au référentiel nu. D'après ce que j'ai lu, le dépôt nu n'a PAS "d'arbre de travail", donc si je clone le dépôt nu, je n'aurai pas "d'arbre de travail".

Je suppose que l'arborescence de travail stocke les informations de validation, les branches, etc. du projet. Cela n'apparaîtrait pas dans le repo nu. Il me semble donc préférable de "pousser" les commits vers le repo avec l'arbre de travail.

Alors, pourquoi devrais-je utiliser le dépôt nu et pourquoi pas? Quelle est la différence pratique? Cela ne serait pas avantageux pour plus de personnes travaillant sur un projet, je suppose.

Quelles sont vos méthodes pour ce genre de travail? Suggestions?

AeroCross
la source
4
AeroCross, vous pouvez cloner un référentiel nu pour créer un référentiel non nu (c'est-à-dire, qui a un espace de travail). Ainsi, en utilisant git clonevous pouvez librement convertir entre les référentiels nus et non nus.
Derek Mahar
13
@AeroCross: Il ne s'agit pas de convertir; peu importe ce qui est à l'autre bout. Si vous exécutez, git clone --barevous obtiendrez un dépôt nu, et si vous exécutez git clone, vous obtiendrez un non-nu. Chaque projet public que vous avez déjà cloné (hébergé sur github, par exemple) est un référentiel nu à l'autre bout.
Cascabel
1
Jefromi, je corrigeais le point d'AeroCross, "donc si je clone le référentiel nu, je n'aurai pas un" arbre de travail "", donc c'est une sorte de conversion. Et tous les projets publics ne doivent pas être un simple référentiel. C'est juste le choix typique car un référentiel nu est plus efficace en termes d'espace car il n'a pas d'arbre de travail (il est aussi efficace en espace que tout référentiel qui n'a pas d'arbre de travail).
Derek Mahar
2
@Derek: Mais le fait est que, dès qu'il trouve le répertoire .git, la récupération ignore totalement si la télécommande est nue ou non. Il ne se convertit pas. Il récupère simplement ce dont il a besoin de la télécommande et le place là où il doit aller. Il n'y a rien à convertir. C'est ce que j'essayais de souligner au PO. Et je suis bien conscient que les projets publics ne doivent pas être nus, mais parce que les gens ne sont pas stupides, ils le sont essentiellement tous. Je pense avoir fait une généralisation acceptable.
Cascabel
2
Voir Pousser vers un référentiel non nu qui donne une autre excellente explication de l'utilisation du référentiel nu.
Craig McQueen

Réponses:

95

Une autre différence entre un référentiel nu et non nu est qu'un référentiel nu n'a pas de référentiel d' origine distant par défaut :

~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

À partir de la page de manuel pour git clone --bare:

De plus, les têtes de branche de la télécommande sont copiées directement dans les têtes de branche locales correspondantes, sans les mapper aux références / télécommandes / origine /. Lorsque cette option est utilisée, ni les branches de suivi à distance ni les variables de configuration associées ne sont créées.

Vraisemblablement, lorsqu'il crée un référentiel nu, Git suppose que le référentiel nu servira de référentiel d'origine pour plusieurs utilisateurs distants, donc il ne crée pas l'origine distante par défaut. Cela signifie que les opérations de base git pullet git pushne fonctionneront pas, car Git suppose que sans espace de travail, vous n'avez pas l'intention de valider les modifications du référentiel nu:

~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$ 
Derek Mahar
la source
1
Oui, je suis d'accord que c'est sans doute la différence la plus importante entre les référentiels Git nus et non nus. Le fait qu'un référentiel non nu possède un espace de travail, mais pas un référentiel nu est une différence importante, mais git clone --no-checkoutpeut également créer un référentiel non nu sans fichiers d'espace de travail.
Derek Mahar
10
Un référentiel non dénudé n'a pas nécessairement une "origine" distante par défaut non plus.
mipadi
2
Vous pouvez créer un référentiel Git simplement avec git init, ce qui créera un dépôt non nu sans aucune télécommande spécifiée.
mipadi
1
mipadi, c'est vrai, mais ce n'est pas non plus un clone.
Derek Mahar
1
Ceci est une erreur. Un référentiel aura une origine par défaut s'il a été cloneédité. S'il a été initédité localement, il n'aura pas une telle origine. Cela n'a rien à voir avec le fait qu'il soit nu ou non.
Noufal Ibrahim
62

La distinction entre un référentiel Git nu et non nu est artificielle et trompeuse car un espace de travail ne fait pas partie du référentiel et un référentiel ne nécessite pas d'espace de travail. À strictement parler, un référentiel Git comprend les objets qui décrivent l'état du référentiel. Ces objets peuvent exister dans n'importe quel répertoire, mais existent généralement dans le .gitrépertoire du répertoire de niveau supérieur de l'espace de travail. L'espace de travail est une arborescence de répertoires qui représente une validation particulière dans le référentiel, mais elle peut exister dans n'importe quel répertoire ou pas du tout. La variable d'environnement $GIT_DIRrelie un espace de travail au référentiel dont il est issu.

Les commandes Git git cloneet les git initdeux ont des options --barequi créent des référentiels sans espace de travail initial. Il est regrettable que Git fusionne les deux concepts distincts, mais liés, d'espace de travail et de référentiel, puis utilise le terme déroutant nu pour séparer les deux idées.

Derek Mahar
la source
61

Un dépôt nu n'est rien d'autre que le dossier .git lui-même, c'est-à-dire que le contenu d'un dépôt nu est le même que le contenu du dossier .git à l' intérieur de votre dépôt de travail local.

  • Utilisez le référentiel nu sur un serveur distant pour permettre à plusieurs contributeurs de pousser leur travail.
  • Non dénudé - Celui qui a un arbre de travail a du sens sur la machine locale de chaque contributeur de votre projet.
Deepak Sharma
la source
60

5 ans trop tard, je sais, mais personne n'a répondu à la question:

Alors, pourquoi devrais-je utiliser le dépôt nu et pourquoi pas? Quelle est la différence pratique? Cela ne serait pas avantageux pour plus de personnes travaillant sur un projet, je suppose.

Quelles sont vos méthodes pour ce genre de travail? Suggestions?

Pour citer directement le livre de Loeliger / MCullough (978-1-449-31638-9, p196 / 7):

Un référentiel nu peut sembler peu utile, mais son rôle est crucial: servir de point focal faisant autorité pour le développement collaboratif. Autres développeurs cloneet à fetchpartir du référentiel nu et pushmises à jour de celui-ci ... si vous configurez un référentiel dans lequel les développeurs pushchangent, il doit être nu. En fait, il s'agit d'un cas particulier de la meilleure pratique plus générale selon laquelle un référentiel publié doit être nu.

EML
la source
19

Un référentiel non nu possède simplement une arborescence de travail extraite. L'arbre de travail ne stocke aucune information sur l'état du référentiel (branches, balises, etc.); au lieu de cela, l'arborescence de travail n'est qu'une représentation des fichiers réels dans le référentiel, ce qui vous permet de travailler (éditer, etc.) les fichiers.

mipadi
la source
Cela signifie donc que je peux ajouter des branches, des balises, etc. au référentiel nu puis passer du nu au référentiel non-nu / de production?
AeroCross
2
mipadi, un référentiel non nu peut ne pas avoir d'arbre extrait. C'est le cas si vous créez un référentiel non nu avec git clone --no-checkout. Dans ce cas, le référentiel non nu a un emplacement pour l'espace de travail, mais Git ne récupère aucun fichier dans cet espace de travail.
Derek Mahar
17

Un référentiel nu présente des avantages dans

  • utilisation réduite du disque
  • moins de problèmes liés à la poussée à distance (car aucun arbre de travail n'est là pour se désynchroniser ou avoir des changements conflictuels)
sehe
la source
3
Donc, le référentiel nu est le meilleur moyen / recommandé de travailler avec plusieurs personnes sans accès à LEURS référentiels? (Un peu comme SVN?)
AeroCross
2
AeroCross, je dirais qu'un référentiel nu est un bon choix pour ce scénario.
Derek Mahar
12

Le référentiel non nu vous permet (dans votre arborescence de travail) de capturer les modifications en créant de nouveaux commits.

Les référentiels nus ne sont modifiés qu'en transportant les modifications à partir d'autres référentiels.

Nitine
la source
10

Je ne suis certainement pas un "expert" Git. J'ai utilisé TortoiseGit pendant un certain temps et je me demandais de quoi il parlait quand il m'a demandé si je voulais faire un dépôt "nu" chaque fois que j'en créais un. Je lisais ce tutoriel: https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init et il résout le problème, mais je ne comprenais toujours pas bien le concept. Celui-ci a beaucoup aidé: http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html . Maintenant, le premier est également logique!

Selon ces sources, en bref, un dépôt "nu" est utilisé sur un serveur sur lequel vous souhaitez configurer un point de distribution. Il n'est pas destiné à être utilisé sur votre ordinateur local. Vous transférez généralement les validations de votre ordinateur local vers un référentiel nu sur un serveur distant, et vous et / ou d'autres tirez de ce référentiel nu vers votre ordinateur local. Ainsi, votre référentiel de stockage / distribution à distance GitHub, Assembla, etc. est un exemple où un référentiel "nu" est créé. Vous en feriez un vous-même si vous mettiez en place votre propre "centre de partage" analogue.

BuvinJ
la source
ooooh maintenant je comprends
Fuseteam
9

Un dépôt Git par défaut / non nu contient deux éléments d'état:

  1. Un instantané de tous les fichiers du référentiel (c'est ce que signifie "arbre de travail" dans le jargon Git)
  2. Un historique de toutes les modifications apportées à tous les fichiers qui ont déjà été dans le référentiel (il ne semble pas y avoir un morceau concis de jargon Git qui englobe tout cela)

L' instantané est ce que vous pensez probablement comme votre projet: vos fichiers de code, les fichiers de construction, les scripts d'aide et tout ce que vous versionnez avec Git.

L' historique est l'état qui vous permet d'extraire un autre commit et d'obtenir un instantané complet de l'apparence des fichiers de votre référentiel lorsque ce commit a été ajouté. Il se compose d'un tas de structures de données internes à Git avec lesquelles vous n'avez probablement jamais interagi directement. Surtout, l'historique ne stocke pas seulement les métadonnées (par exemple "L'utilisateur U a ajouté autant de lignes au fichier F au temps T dans le cadre de la validation C"), il stocke également les données (par exemple "L'utilisateur U a ajouté ces lignes exactes au fichier F" ).

L'idée clé d'un référentiel nu est que vous n'avez pas réellement besoin d'avoir l'instantané. Git conserve l'instantané, car il est pratique pour les humains et les autres processus non-Git qui veulent interagir avec votre code, mais l'instantané ne fait que dupliquer l'état qui est déjà dans l'historique.

Un référentiel nu est un référentiel Git qui n'a pas d'instantané. Il stocke juste l'histoire.

Pourquoi voudriez-vous cela? Eh bien, si vous allez uniquement interagir avec vos fichiers à l'aide de Git (c'est-à-dire que vous n'allez pas modifier vos fichiers directement ou les utiliser pour créer un exécutable), vous pouvez économiser de l'espace en ne restant pas sur l'instantané. En particulier, si vous maintenez une version centralisée de votre référentiel sur un serveur quelque part (c'est-à-dire que vous hébergez essentiellement votre propre GitHub), ce serveur devrait probablement avoir un référentiel nu (vous utiliseriez toujours un référentiel non nu sur votre machine locale, car vous voudrez probablement modifier votre instantané).

Si vous voulez une explication plus approfondie des dépôts nus et un autre exemple d'utilisation, j'ai rédigé un article de blog ici: https://stegosaurusdormant.com/bare-git-repo/

Greg Owen
la source
4

Ce n'est pas une nouvelle réponse, mais cela m'a aidé à comprendre les différents aspects des réponses ci-dessus (et c'est trop pour un commentaire).

En utilisant Git Bash, essayez simplement:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/

me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 .git/

me@pc MINGW64 /c/Test (master)
$ cd .git

me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr  1 11:35 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:35 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:35 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 objects/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 refs/

Idem avec git --bare:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/

me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr  1 11:36 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:36 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:36 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 objects/
Christoph
la source
2

$ git help repository-layout

Un référentiel Git se décline en deux versions différentes:

  • un répertoire .git à la racine de l'arborescence de travail;
  • un répertoire .git qui est un référentiel nu (c'est-à-dire sans sa propre arborescence de travail), qui est généralement utilisé pour échanger des historiques avec d'autres personnes en le poussant et en le récupérant.
MichK
la source