FreeToGenerate.com

Écrivez le fichier, puis voyez ce que git en fait réellement. Mesuré, non recopié du manuel.

Votre .gitattributes

Tester un chemin

Relatif à la racine du dépôt, avec des barres obliques. C'est la question à laquelle le fichier ne répond pas à la simple lecture : quelle ligne l'emporte.

Celui qui clone votre dépôt possède l'un de ces trois réglages, et vous ne le contrôlez pas. C'est tout l'objet du panneau ci-dessous.

Attributs pour ce chemin

AttributÉtatDe
textauto*

Ce que git fera réellement des fins de ligne

stocké dans le dépôt
LF
écrit dans sa copie de travail
CRLF

Non fixé. Changez le réglage ci-dessus et regardez ce panneau bouger : c'est un réglage propre à chacun qui décide de vos fichiers.

Ceci a été mesuré, pas recopié du manuel

Le tableau ci-dessus provient de la validation d'un même fichier en CRLF dans vingt et un dépôts jetables — toutes les combinaisons de trois réglages de core.autocrlf et de sept lignes d'attributs — puis de la question posée à git : qu'est-il réellement arrivé dans la base d'objets, et, après suppression et restauration du fichier, dans la copie de travail.

Le résultat principal est que, sans .gitattributes, ce que votre dépôt stocke dépend de la personne qui a validé. Le même fichier entre en CRLF avec core.autocrlf=false et en LF avec true ou input, et rien dans votre propre copie ne dit lequel s'est produit. Ajoutez n'importe quel attribut text et cette variation disparaît : les trois réglages ont produit des octets identiques.

Ce que l'on comprend de travers, c'est ce que text=auto ne fait pas. Il fixe le dépôt et laisse la copie de travail tranquille : réextrait, le même fichier arrive en CRLF pour deux des trois réglages et en LF pour le troisième. Seuls eol=lf ou eol=crlf fixent les deux extrémités. Et eol=crlf stocke tout de même du LF, car c'est une instruction sur l'extraction et non sur le stockage — ce qui donne l'impression qu'elle ne fait rien tant qu'on ne regarde pas au bon endroit.

Les motifs sont ceux de gitignore, à une exception dangereuse près

La correspondance se comporte comme on l'attend d'un .gitignore : un motif contenant une barre est mesuré depuis le répertoire de son propre .gitattributes, un motif sans barre correspond à un nom à n'importe quelle profondeur, ** franchit les répertoires et en correspond aussi à aucun. La précédence va par position — la dernière ligne correspondante l'emporte et la précision ne compte pour rien — tandis qu'un .gitattributes plus profond dans l'arborescence l'emporte sur un plus superficiel, quel que soit l'ordre de lecture de git.

L'exception est le point d'exclamation, et elle mérite d'être connue car elle échoue en silence. Dans un .gitignore, un ! initial nie le motif. Dans un .gitattributes il ne fait absolument rien : une ligne commençant par ! n'est tout simplement pas prise en charge, et git conserve la valeur précédente. Pour retirer un attribut on place un tiret devant l'attribut et non devant le motif, et pour le ramener à non spécifié on y place le point d'exclamation.

Comportement mesuré face à git lui-même ; les sondes sont dans le dépôt. Rien n'est envoyé : la correspondance se calcule dans cet onglet.

Aussi disponible en : English · Español · Português · العربية

Générateur de .gitattributes

Générez un fichier .gitattributes et testez n'importe quel chemin : quelle ligne l'emporte, et quelles fins de ligne git stockera puis remettra à qui clonera votre dépôt.

Qu'est-ce qu'un fichier .gitattributes ?

Un fichier .gitattributes indique à git comment traiter certains chemins. Il vit dans votre dépôt, il est validé comme n'importe quoi d'autre, et il décide quels fichiers comptent comme du texte, lesquels sont binaires, comment ils sont comparés et fusionnés et — la partie pour laquelle presque tout le monde arrive ici — ce qu'il advient des fins de ligne à l'aller comme au retour.

Le format est un motif suivi d'attributs, une règle par ligne, exactement la forme d'un .gitignore. Cette familiarité explique l'essentiel des ennuis : les motifs sont bien ceux de gitignore, mais un élément de la syntaxe signifie tout autre chose, et l'attribut vers lequel chacun se tourne en fait moins que son nom ne le laisse croire.

Cet outil couvre les deux moitiés. Vous modifiez le fichier, vous lui donnez un chemin, et il vous dit quelle ligne l'emporte, dans quel état finit chaque attribut, et ce que git va réellement stocker et extraire — y compris pour le réglage présent sur la machine de quelqu'un d'autre, que vous ne contrôlez pas.

Comment l'utiliser

  1. Partez du fichier affiché. C'est un point de départ raisonnable : normaliser le texte, fixer les scripts shell en LF et les .bat en CRLF, marquer les binaires habituels et empêcher git de comparer un fichier de verrouillage. Modifiez-le directement.
  2. Saisissez un chemin à vérifier. Relatif à la racine du dépôt. Chaque attribut correspondant est affiché avec le motif qui l'a fourni : vous voyez donc quelle ligne l'a réellement emporté, et non celle que vous visiez.
  3. Changez son core.autocrlf. Ces trois boutons représentent le réglage de la machine de qui clonera votre dépôt. Regardez le panneau des fins de ligne pendant que vous les pressez : s'il bouge, vos fichiers dépendent d'un réglage que vous ne voyez pas.

Ce que font réellement les fins de ligne, mesuré

Cette partie a été mesurée, non lue. Le même fichier en CRLF a été validé dans vingt et un dépôts jetables — toutes les combinaisons de trois réglages de core.autocrlf et de sept lignes d'attributs différentes — puis on a demandé à git ce qui se trouvait dans la base d'objets et, après suppression et restauration du fichier, dans la copie de travail.

Sans .gitattributes, ce que votre dépôt stocke dépend de la personne qui a validé. Le même fichier entre en CRLF avec core.autocrlf=false et en LF avec true ou input. Rien dans votre propre copie ne dit lequel s'est produit, et c'est pourquoi cela se manifeste par une demande de fusion pleine de fichiers entiers modifiés plutôt que par une erreur. Ajoutez n'importe quel attribut text et cette variation disparaît : les trois réglages ont produit des octets identiques.

La surprise est ce que text=auto ne fait pas. Il fixe le dépôt et laisse la copie de travail tranquille : réextrait, le même fichier arrive en CRLF pour deux des trois réglages et en LF pour le troisième. Une équipe qui ajoute une seule ligne de text=auto a donc rendu son historique cohérent sans faire concorder ses copies de travail. Seuls eol=lf ou eol=crlf fixent les deux extrémités.

Et eol=crlf stocke du LF. C'est une instruction sur l'extraction, non sur le stockage : si vous inspectez l'objet, vous y trouverez du LF et conclurez que la ligne n'a rien fait. Elle a agi, simplement à l'autre bout.

Les motifs sont ceux de gitignore, avec une exception qui échoue en silence

La correspondance se comporte comme cette forme familière le laisse penser. Un motif contenant une barre est mesuré depuis le répertoire de son propre .gitattributes ; un motif sans barre correspond à un nom à n'importe quelle profondeur en dessous. Le double astérisque franchit les répertoires et — mesuré, car on suppose facilement le contraire — correspond aussi à aucun répertoire, si bien que sub/**/*.txt couvre sub/a.txt autant que sub/deep/a.txt. Les classes de caractères fonctionnent.

La précédence va par position et non par précision : la dernière ligne correspondante l'emporte, et qu'un motif soit plus précis ne compte pour rien. C'est la règle qu'a aussi EditorConfig, et celle que l'on comprend à l'envers dans les deux cas. Entre fichiers, un .gitattributes plus profond dans l'arborescence l'emporte sur un plus superficiel, quel que soit l'ordre de lecture de git.

L'exception est le point d'exclamation. Dans un .gitignore, un ! initial nie le motif. Dans un .gitattributes il n'est pas pris en charge du tout : une ligne commençant par ! ne fait rien, et la valeur précédente reste en vigueur. Ni erreur ni avertissement. Pour retirer un attribut, on place un tiret devant l'attribut et non devant le motif ; pour le ramener à non spécifié, on y place le point d'exclamation.

Une dernière chose à savoir, car c'est la ligne la plus fréquente de tout fichier réel : binary n'est pas un attribut mais une macro. Elle se déploie en désactivant text, diff et merge ensemble, et c'est pourquoi marquer un chemin binary écrase correctement un text=auto antérieur au lieu de coexister avec lui.

Limites assumées

Ceci modélise les règles, pas votre dépôt. Un vrai projet peut comporter plusieurs .gitattributes à des profondeurs différentes, et git lit également .git/info/attributes ainsi qu'un fichier global situé hors du dépôt — ni l'un ni l'autre n'étant validés, ni présents chez quiconque d'autre. Ce qui est modélisé ici, c'est le fichier validé et les règles qu'il contient, là où se niche presque toujours la partie déroutante.

Le panneau des fins de ligne prédit ce que git fait d'un fichier texte comportant actuellement des CRLF, puisque c'est le cas avec lequel on arrive. Un fichier déjà entièrement en LF, ou aux fins de ligne mélangées, se comporte d'une manière que le panneau ne cherche pas à représenter.

Modifier un .gitattributes ne change pas les fichiers déjà validés. Git applique les nouvelles règles la prochaine fois qu'un fichier lui passe entre les mains : un dépôt qui stockait des CRLF continue donc d'en stocker jusqu'à ce que quelque chose réécrive ces fichiers. C'est à cela que sert l'option de renormalisation, et elle produit exactement l'énorme différence que vous imaginez — raison pour laquelle mieux vaut le faire délibérément que le découvrir ensuite.

Pourquoi est-ce gratuit ?

Tout tourne dans votre navigateur. Confronter un chemin à un motif ne coûte rien sur votre propre machine : aucun serveur à financer, aucun compte à créer.

Rien de ce que vous saisissez n'est envoyé, conservé ni journalisé. Les noms de fichiers et l'arborescence en disent long sur une base de code privée, et la façon fiable de garder cela privé est de ne l'envoyer nulle part.