Comment Git gère-t-il les liens symboliques?

1607

Si j'ai un fichier ou un répertoire qui est un lien symbolique et que je le valide dans un référentiel Git, que se passe-t-il?

Je suppose qu'il le laisse comme un lien symbolique jusqu'à ce que le fichier soit supprimé, puis si vous retirez le fichier d'une ancienne version, il crée simplement un fichier normal.

Que fait-il lorsque je supprime le fichier auquel il fait référence? Commet-il simplement le lien pendant?

Alex
la source
19
.gitignorevoit le lien symbolique comme un fichier et non comme un dossier.
0xcaff
6
Eh bien, évidemment, la question ne se limite pas à ce que cette réponse implique. Par exemple, je me demande ce qui suit: si je crée un lien sym dans mon référentiel vers un fichier volumineux dans ce référentiel, que je pousse les modifications, puis que je tire ces modifications sur une autre machine, que se passera-t-il? Le fichier volumineux sera-t-il stocké en tant que fichier volumineux aux deux emplacements, ou le lien sym sera-t-il conservé, de sorte que sur la nouvelle machine, le fichier de lien pointe vers le fichier volumineux d'origine?
jvriesem
7
Il s'agit d'un ancien fil de discussion mais ce commentaire peut toujours être utile. En réponse à jviesem, un lien logiciel est essentiellement un fichier avec le nom d'un autre fichier. Donc, une fois que vous le tirez sur une autre machine, le lien sera téléchargé et il aura le nom du gros fichier sur le système de fichiers d'origine. Si sur la nouvelle machine le nom n'est pas valide, alors le lien aura un nom invalide. Le gros fichier ne sera pas téléchargé sur la nouvelle machine.
lasaro
6
@lasaro, la façon d'éviter les liens cassés dans un référentiel git est de toujours utiliser des chemins relatifs lors de la création des liens symboliques, en utilisant ../..au besoin.
Wildcard
8
Notez que dans la plupart des versions de Windows, vous avez besoin d'autorisations élevées pour créer un lien symbolique. Si vous êtes sous Windows et git pullcréez un fichier au lieu d'un lien symbolique, essayez d'exécuter votre client Git en tant qu'administrateur.
axmrnv

Réponses:

1347

Git stocke simplement le contenu du lien (c'est-à-dire le chemin de l'objet du système de fichiers auquel il est lié) dans un «blob» comme il le ferait pour un fichier normal. Il stocke ensuite le nom, le mode et le type (y compris le fait qu'il s'agit d'un lien symbolique) dans l'objet arborescent qui représente son répertoire conteneur.

Lorsque vous extrayez une arborescence contenant le lien, elle restaure l'objet en tant que lien symbolique, que l'objet du système de fichiers cible existe ou non.

Si vous supprimez le fichier référencé par le lien symbolique, cela n'affecte en rien le lien symbolique contrôlé par Git. Vous aurez une référence pendante. Il appartient à l'utilisateur de supprimer ou de modifier le lien pour pointer vers quelque chose de valide si nécessaire.

CB Bailey
la source
328
BTW. Si vous utilisez un système de fichiers comme FAT qui ne prend pas en charge les liens symboliques et que votre référentiel les utilise, vous pouvez définir la core.symlinksvariable de configuration sur false et les liens symboliques seront extraits sous forme de petits fichiers de texte brut contenant le texte du lien.
Jakub Narębski
14
@ JakubNarębski J'ai déjà vu ça auparavant. Il y avait un fichier texte dans notre référentiel avec une ligne, un chemin vers une bibliothèque que nous utilisons. Impossible de comprendre quel était son objectif. Je sais maintenant ce qui s'est passé.
Matt K
25
J'hésite à commenter une réponse très appréciée, mais je pense que le libellé "comme il le ferait pour un fichier normal" pourrait induire les nouveaux arrivants en erreur.
Matthew Hannigan
10
(manqué de temps d'édition) C'est comme un fichier normal uniquement dans la mesure où le contenu est dans un blob. La différence critique est que pour un fichier normal, le blob est le contenu du fichier, mais pour un lien symbolique, le blob a le chemin d'accès du fichier auquel il est lié. @ JakubNarębski En ce qui concerne les "petits fichiers texte brut" .. Vous espérez qu'ils sont petits et texte mais bien sûr, un blob est un blob et pourrait potentiellement être énorme et binaire. Voir stackoverflow.com/questions/18411200/… pour savoir quand un fichier est mal tapé en tant que lien symbolique.
Matthew Hannigan
2
Assurez-vous de vérifier vos paramètres globaux pour les liens symboliques et les paramètres locaux pour les liens symboliques. Si les paramètres ont été copiés à partir de TortiseGit ou de Windows, vous pourriez avoir des symlinks = falseproblèmes avec eux.
phyatt
251

Vous pouvez découvrir ce que Git fait avec un fichier en voyant ce qu'il fait lorsque vous l'ajoutez à l'index. L'index est comme un pré-commit. Avec l'index validé, vous pouvez utiliser git checkoutpour ramener tout ce qui était dans l'index dans le répertoire de travail. Alors, que fait Git lorsque vous ajoutez un lien symbolique à l'index?

Pour découvrir, tout d'abord, faites un lien symbolique:

$ ln -s /path/referenced/by/symlink symlink

Git ne connaît pas encore ce fichier. git ls-filesvous permet d'inspecter votre index ( sortie de type -simpressions stat):

$ git ls-files -s ./symlink
[nothing]

Maintenant, ajoutez le contenu du lien symbolique au magasin d'objets Git en l'ajoutant à l'index. Lorsque vous ajoutez un fichier à l'index, Git stocke son contenu dans le magasin d'objets Git.

$ git add ./symlink

Alors, qu'est-ce qui a été ajouté?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

Le hachage est une référence à l'objet compressé qui a été créé dans le magasin d'objets Git. Vous pouvez examiner cet objet si vous regardez .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cdans la racine de votre référentiel. Il s'agit du fichier que Git stocke dans le référentiel, que vous pourrez consulter ultérieurement. Si vous examinez ce fichier, vous verrez qu'il est très petit. Il ne stocke pas le contenu du fichier lié.

(Notez que 120000le mode est répertorié dans la ls-filessortie. Ce serait quelque chose comme 100644pour un fichier normal.)

Mais que fait Git avec cet objet lorsque vous le retirez du référentiel et dans votre système de fichiers? Cela dépend de la core.symlinksconfiguration. De man git-config:

core.symlinks

Si faux, les liens symboliques sont extraits sous forme de petits fichiers simples contenant le texte du lien.

Ainsi, avec un lien symbolique dans le référentiel, lors de la vérification, vous obtenez soit un fichier texte avec une référence à un chemin complet du système de fichiers, soit un lien symbolique approprié, selon la valeur de la core.symlinksconfiguration.

Dans les deux cas, les données référencées par le lien symbolique ne sont pas stockées dans le référentiel.

Dmitry Minkovsky
la source
1
Super
147

"Note de l'éditeur": Ce message peut contenir des informations obsolètes. Veuillez consulter les commentaires et cette question concernant les changements dans Git depuis 1.6.1.

Répertoires liés symboliquement:

Il est important de noter ce qui se passe lorsqu'il existe un répertoire qui est un lien logiciel. Tout pull Git avec une mise à jour supprime le lien et en fait un répertoire normal. C'est ce que j'ai appris à la dure. Quelques aperçus ici et ici.

Exemple

Avant

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

Après git pullET quelques mises à jour trouvées

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir
Shekhar
la source
4
Il convient de noter que ces avertissements concernant les répertoires de liens symboliques ne s'appliquent pas aux liens symboliques versionnés. Le cas de bord principal en question était celui des gens qui lient une partie ou la totalité de l'arborescence de travail à un chemin différent (par exemple sur une partition différente avec plus d'espace disque) et s'attendent à ce que git vérifie le code via le lien symbolique existant. Autrement dit, si vous avez un projet qui contient des liens symboliques versionnés vers des fichiers ou des répertoires, le comportement normal de lien symbolique en tant qu'objet blob conservera les liens symboliques, correctement les modifications de version de ces liens symboliques et fonctionnera comme prévu.
John Whitley
Le comportement ci-dessus testé avec git 1.6.5.6; mais je soupçonne fortement que le comportement versionné est correct dans git depuis un certain temps.
John Whitley
22
Ce comportement est-il présent sur toutes les versions de git ou cela a-t-il été corrigé?
jbotnik
24
Il semble que ce comportement soit maintenant corrigé, voir: stackoverflow.com/a/1943656/1334781
Ron Wertlen
2
Shekar: Allez-vous modifier votre réponse pour refléter les changements dans git ces dernières années?
einpoklum