Fonctionnement des conversions de fin de ligne avec git core.autocrlf entre différents systèmes d'exploitation

220

J'ai lu de nombreuses questions et réponses sur Stack Overflow ainsi que de la documentation git sur le fonctionnement du paramètre core.autocrlf .

Voici ma compréhension de ce que j'ai lu:

Les clients Unix et Mac OSX (pré-OSX utilise CR) utilisent les terminaisons de ligne LF.
Les clients Windows utilisent des fins de ligne CRLF.

Lorsque core.autocrlf est défini sur true sur le client, le référentiel git stocke toujours les fichiers au format de fin de ligne LF et les fins de ligne dans les fichiers sur le client sont converties dans les deux sens lors de l'extraction / validation pour les clients (c'est-à-dire Windows) qui utilisent non -LF fin de ligne, quel que soit le format des fichiers de fin de ligne sur le client (cela n'est pas conforme à la définition de Tim Clem - voir la mise à jour ci-dessous).

Voici une matrice qui essaie de documenter la même chose pour les paramètres 'input' et 'false' de core.autocrlf avec des points d'interrogation où je ne suis pas sûr du comportement de conversion de fin de ligne.

Mes questions sont:

  1. Quels devraient être les points d'interrogation?
  2. Cette matrice est-elle correcte pour les "non-points d'interrogation"?

Je mettrai à jour les points d'interrogation des réponses car un consensus semble se former.

                       valeur core.autocrlf
            vrai entrée faux
-------------------------------------------------- --------
commettre | convertir? ?
nouveau | en LF (convertir en LF?) (pas de conversion?)

commettre | convertir en ? non
existant | Conversion LF (convertir en LF?)

caisse | convertir en ? non
existant | Conversion CRLF (pas de conversion?)

Je ne suis pas vraiment à la recherche d'opinions sur les avantages et les inconvénients des différents paramètres. Je cherche juste des données qui indiquent clairement comment attendre que git fonctionne avec chacun des trois paramètres.

-

Mise à jour 17/04/2012 : Après avoir lu l'article de Tim Clem lié par JJD dans les commentaires, j'ai modifié certaines des valeurs dans les valeurs "inconnues" dans le tableau ci-dessus, ainsi que changé "checkout existant | true pour convertir" en CRLF au lieu de convertir en client ". Voici les définitions qu'il donne, qui sont plus claires que tout ce que j'ai vu ailleurs:

core.autocrlf = false

C'est la valeur par défaut, mais la plupart des gens sont encouragés à changer cela immédiatement. Le résultat de l'utilisation de false est que Git ne dérange jamais les fins de ligne de votre fichier. Vous pouvez archiver des fichiers avec LF ou CRLF ou CR ou un mélange aléatoire de ces trois et Git s'en fiche. Cela peut rendre les différences plus difficiles à lire et les fusionner plus difficiles. La plupart des gens travaillant dans un monde Unix / Linux utilisent cette valeur car ils n'ont pas de problèmes CRLF et ils n'ont pas besoin que Git fasse un travail supplémentaire chaque fois que des fichiers sont écrits dans la base de données d'objets ou écrits dans le répertoire de travail.

core.autocrlf = true

Cela signifie que Git traitera tous les fichiers texte et s'assurera que CRLF est remplacé par LF lors de l'écriture de ce fichier dans la base de données d'objets et remettra tous les LF en CRLF lors de l'écriture dans le répertoire de travail. Il s'agit du paramètre recommandé sous Windows car il garantit que votre référentiel peut être utilisé sur d'autres plates-formes tout en conservant CRLF dans votre répertoire de travail.

core.autocrlf = entrée

Cela signifie que Git traitera tous les fichiers texte et s'assurera que CRLF est remplacé par LF lors de l'écriture de ce fichier dans la base de données d'objets. Il ne fera cependant pas l'inverse. Lorsque vous lisez des fichiers de la base de données d'objets et les écrivez dans le répertoire de travail, ils auront toujours des LF pour indiquer la fin de la ligne. Ce paramètre est généralement utilisé sur Unix / Linux / OS X pour empêcher les CRLF d'être écrits dans le référentiel. L'idée étant que si vous colliez du code à partir d'un navigateur Web et introduisiez accidentellement des CRLF dans l'un de vos fichiers, Git s'assurait qu'ils étaient remplacés par des LF lorsque vous écriviez dans la base de données d'objets.

L'article de Tim est excellent, la seule chose à laquelle je pense qu'il manque, c'est qu'il suppose que le référentiel est au format LF, ce qui n'est pas nécessairement vrai, en particulier pour les projets Windows uniquement.

La comparaison de l'article de Tim avec la réponse la plus votée à ce jour par jmlane montre un accord parfait sur les paramètres true et input et un désaccord sur le paramètre false.

Michael Maddox
la source
7
Rester autocrlfà faux semble tellement plus facile;) stackoverflow.com/questions/2333424/…
VonC
@VonC: J'ai lu ça et je pense que je le comprends, mais je n'ai pas forcément le choix. Je travaille avec des dépôts git que je ne contrôle pas et qui exigent que je définisse la valeur d'une certaine manière.
Michael Maddox
5
Ce ne serait pas bien si Windows se normalisait aussi en LF? Mac était CR (avant v10) mais est maintenant normalisé en LF.
Brett Ryan
3
Je dois ajouter un lien vers le grand article de Timothy Clem - veuillez lire l'intégralité de Mind the End of Your Line .
JJD
1
Scénario: je suis un développeur Linux / Windows divisé. J'utilise uniquement des éditeurs de texte qui peuvent reconnaître les deux types de fins de ligne (IE. Vim, eclipse). J'ai seulement besoin (envie) de travailler avec des fichiers se terminant par LF. J'ai actuellement core.autocrlf = input défini dans ma configuration globale de git. Suis-je prêt à partir? Aurai-je jamais un conflit?
Chris

Réponses:

128

La meilleure explication du core.autocrlffonctionnement se trouve sur la page de manuel gitattributes , dans la textsection attribut.

Voici comment core.autocrlfsemble fonctionner actuellement (ou du moins depuis la v1.7.2 d'après ce que je sais):

  • core.autocrlf = true
    1. Les fichiers texte extraits du référentiel qui ne contiennent que des LFcaractères sont normalisés CRLFdans votre arborescence de travail; les fichiers qui contiennent CRLFdans le référentiel ne seront pas touchés
    2. Les fichiers texte qui ne contiennent que des LFcaractères dans le référentiel sont normalisés de CRLFà LFlorsqu'ils sont validés dans le référentiel. Les fichiers qui contiennent CRLFdans le référentiel seront validés intacts.
  • core.autocrlf = input
    1. Les fichiers texte extraits du référentiel conserveront les caractères EOL d'origine dans votre arborescence de travail.
    2. Les fichiers texte de votre arborescence de travail contenant des CRLFcaractères sont normalisés LFlorsqu'ils sont renvoyés dans le référentiel.
  • core.autocrlf = false
    1. core.eol dicte les caractères EOL dans les fichiers texte de votre arborescence de travail.
    2. core.eol = nativepar défaut, ce qui signifie que les EOL Windows sont CRLFet que les EOL * nix sont LFdans des arborescences de travail.
    3. Les gitattributesparamètres du référentiel déterminent la normalisation des caractères EOL pour les validations dans le référentiel (la normalisation par défaut est les LFcaractères).

Je viens tout juste de faire des recherches sur cette question et je trouve également que la situation est très compliquée. Le core.eolparamètre a certainement aidé à clarifier la façon dont les caractères EOL sont gérés par git.

jmlane
la source
3
pour autocrlf = true ne devrait pas être le suivant? Les fichiers texte qui ne contiennent que des caractères EOL CRLF dans le référentiel sont normalisés de CRLF à LF lorsqu'ils sont validés dans le référentiel. Les fichiers qui contiennent LF dans le référentiel seront validés intacts.
Piotr Lewandowski
2
Pour moi, même si autocrlf = false git convertissait l'EOL en CRLF. Après avoir lu cette réponse, j'ai réalisé que mon fichier .gitattribute avait text = auto set qui causait le problème.
irsis
1
Car core.autocrlf = false, si je n'ai pas de gitattributesfichier, cela signifie-t-il qu'il n'y aura pas de normalisation? Ou cela signifie-t-il qu'il utilisera la normalisation par défaut?
Chin
Le .gitattributesfichier ne doit-il pas prévaloir sur la core.autocrlfconfiguration?
Qwerty
63

La question des EOL dans les projets multi-plateformes rend ma vie misérable depuis longtemps. Les problèmes surviennent généralement lorsqu'il existe déjà des fichiers avec des EOL différents et mixtes déjà dans le référentiel . Cela signifie que:

  1. Le référentiel peut avoir différents fichiers avec différents EOL
  2. Certains fichiers du référentiel peuvent avoir une fin de vie mixte, par exemple une combinaison de CRLFet LFdans le même fichier.

Comment cela se produit n'est pas le problème ici, mais cela se produit.

J'ai effectué des tests de conversion sur Windows pour les différents modes et leurs combinaisons.
Voici ce que j'ai obtenu, dans un tableau légèrement modifié:

                 | Conversion résultante lorsque | Conversion résultante lorsque
                 | validation de fichiers avec divers | vérification DE repo -
                 | EOLs EN repo et | avec des fichiers mixtes et
                 | valeur core.autocrlf: | Valeur core.autocrlf:           
-------------------------------------------------- ------------------------------
Fichier | vrai | entrée | faux | vrai | entrée | faux
-------------------------------------------------- ------------------------------
Windows-CRLF | CRLF -> LF | CRLF -> LF | en l'état | en l'état | en l'état | comme si
Unix -LF | en l'état | en l'état | en l'état | LF -> CRLF | en l'état | comme si
Mac -CR | en l'état | en l'état | en l'état | en l'état | en l'état | comme si
Mixte-CRLF + LF | en l'état | en l'état | en l'état | en l'état | en l'état | comme si
Mixte-CRLF + LF + CR | en l'état | en l'état | en l'état | en l'état | en l'état | comme si

Comme vous pouvez le voir, il y a 2 cas où la conversion se produit lors de la validation (3 colonnes de gauche). Dans les autres cas, les fichiers sont validés tels quels.

Lors du paiement (3 colonnes de droite), il n'y a qu'un seul cas où la conversion se produit lorsque:

  1. core.autocrlfest true et
  2. le fichier dans le référentiel a la fin de vie LF.

Le plus surprenant pour moi, et je soupçonne, la cause de nombreux problèmes d'EOL est qu'il n'y a pas de configuration dans laquelle les EOL mixtes comme CRLF+ LFsont normalisés.

Notez également que les "anciens" EOL Mac CRne sont également jamais convertis.
Cela signifie que si un script de conversion EOL mal écrit essaie de convertir un fichier de fin mixte avec CRLFs + LFs, en convertissant simplement LFs en CRLFs, il laissera le fichier en mode mixte avec "solitaire" CRpartout où a a CRLFété converti CRCRLF.
Git ne convertira alors rien, même en truemode, et les ravages d'EOL se poursuivent. Cela m'est réellement arrivé et a vraiment gâché mes fichiers, car certains éditeurs et compilateurs (par exemple VS2010) n'aiment pas les EOL Mac.

Je suppose que la seule façon de vraiment gérer ces problèmes est de normaliser de temps en temps l'ensemble du référentiel en vérifiant tous les fichiers en mode inputou false, en exécutant une normalisation appropriée et en réinitialisant les fichiers modifiés (le cas échéant). Sur Windows, reprenez probablement le travail avec core.autocrlf true.

Adi Shavit
la source
4
Excellente réponse, mais une phrase avec laquelle je ne suis pas d'accord est sur Windows, reprenez probablement le travail aveccore.autocrlf true . Je crois personnellement que cela inputdevrait toujours être utilisé.
G. Demecki du
39

Les choses sont sur le point de changer du côté de la "conversion eol", avec le prochain Git 1.7.2 :

Un nouveau paramètre de configuration core.eolest ajouté / évolué :

Il s'agit d'un remplacement pour la core.eolvalidation "Ajouter" "variable de configuration" qui est actuellement pu(la dernière de ma série).
Au lieu d'impliquer que " core.autocrlf=true" est un remplacement de " * text=auto", cela rend explicite le fait que autocrlfc'est uniquement pour les utilisateurs qui veulent travailler avec des CRLF dans leur répertoire de travail sur un référentiel qui n'a pas de normalisation de fichier texte .
Lorsqu'il est activé, "core.eol" est ignoré.

Introduisez une nouvelle variable de configuration, " core.eol", qui permet à l'utilisateur de définir les fins de ligne à utiliser pour les fichiers normalisés en fin de ligne dans le répertoire de travail.
Il est par défaut " native", ce qui signifie CRLF sur Windows et LF partout ailleurs. Notez que " core.autocrlf" remplace core.eol.
Cela signifie que:

[core]
  autocrlf = true

place les CRLF dans le répertoire de travail même s'il core.eolest défini sur " lf".

core.eol:

Définit le type de fin de ligne à utiliser dans le répertoire de travail pour les fichiers dont la textpropriété est définie.
Les alternatives sont 'lf', 'crlf' et 'native', qui utilise la fin de ligne native de la plateforme.
La valeur par défaut est native.


D'autres évolutions sont à l'étude :

Pour 1.8, j'envisager de faire core.autocrlfsimplement tourner la normalisation et de laisser la ligne de répertoire de travail se termine à la décision core.eol, mais qui sera briser les configurations des gens.


git 2.8 (mars 2016) améliore la façon dont core.autocrlfinfluence le eol:

Voir commettre 817a0c7 (23 février 2016), engager 6e336a5 , engager df747b8 , engager df747b8 (10 février 2016), engager df747b8 , engager df747b8 (10 février 2016), et engager 4b4024f , engager bb211b4 , engager 92cce13 , engager 320d39c , engager 4b4024f , commit bb211b4 , commit 92cce13 , commit 320d39c (05 février 2016) par Torsten Bögershausen ( tboegi) .
(Fusionné par Junio ​​C Hamano - gitster- en commit c6b94eb, 26 févr.2016)

convert.c: refactor crlf_action

Remanier la détermination et l'utilisation de crlf_action.
Aujourd'hui, quand aucun crlfattribut " " n'est défini sur un fichier, crlf_actionest défini sur CRLF_GUESS. Utilisez CRLF_UNDEFINEDplutôt et recherchez " text" ou " eol" comme précédemment.

Remplacez l'ancienne CRLF_GUESSutilisation:

CRLF_GUESS && core.autocrlf=true -> CRLF_AUTO_CRLF
CRLF_GUESS && core.autocrlf=false -> CRLF_BINARY
CRLF_GUESS && core.autocrlf=input -> CRLF_AUTO_INPUT

Précisez ce qui est quoi en définissant:

- CRLF_UNDEFINED : No attributes set. Temparally used, until core.autocrlf
                   and core.eol is evaluated and one of CRLF_BINARY,
                   CRLF_AUTO_INPUT or CRLF_AUTO_CRLF is selected
- CRLF_BINARY    : No processing of line endings.
- CRLF_TEXT      : attribute "text" is set, line endings are processed.
- CRLF_TEXT_INPUT: attribute "input" or "eol=lf" is set. This implies text.
- CRLF_TEXT_CRLF : attribute "eol=crlf" is set. This implies text.
- CRLF_AUTO      : attribute "auto" is set.
- CRLF_AUTO_INPUT: core.autocrlf=input (no attributes)
- CRLF_AUTO_CRLF : core.autocrlf=true  (no attributes)

Comme l'a ajouté torek dans les commentaires :

toutes ces traductions (toute conversion EOL depuis eol=ou autocrlfparamètres et " clean" filtres) sont exécutées lorsque les fichiers se déplacent de l'arborescence de travail vers l'index , c'est -dire pendant git addplutôt qu'à l' git commitheure.
(Notez que git commit -aou --onlyou --includeajoutez des fichiers à l'index à ce moment-là, cependant.)

Pour plus d'informations, voir " Quelle est la différence entre autocrlf et eol ".

VonC
la source
18
Malheureusement, cela n'ajoute pas de clarté pour moi. Il semble qu'ils disent qu'il y a des problèmes avec la mise en œuvre actuelle (ce n'est pas clair quels sont ces problèmes) et qu'ils augmentent la complexité dans un effort pour résoudre ces problèmes non spécifiés. À mon avis, le paramètre core.autocrlf est déjà trop complexe et sous-documenté et cette situation semble empirer. Merci encore pour votre attention.
Michael Maddox
1
Cela ne semble pas être une solution satisfaisante et semble avoir les mêmes problèmes que core.autocrlf. Ma préférence serait que git ne modifie jamais rien automatiquement, mais cela avertirait l'utilisateur qui souhaite ajouter ou valider les mauvaises fins de ligne. Vous auriez donc besoin d'une option de ligne de commande pour permettre à "git add" d'ajouter les "mauvaises" fins de ligne. (probablement git add est le meilleur endroit pour vérifier cela que git commit)
donquixote
Cela obligerait l'utilisateur respectif à modifier les paramètres de son éditeur et à prendre vraiment soin du problème. Même si cela permettrait de laisser les «mauvaises» fins de ligne pour les fichiers de tiers, ou qui sont déjà enregistrés dans le référentiel.
donquixote
@donquixote encore une fois, je suis d'accord. Mais il core.eols'agit de "modifier automatiquement" uniquement ce que vous déclarez explicitement dans un .gitattributesfichier. Ceci est différent de celui core.autocrlfqui s'applique à n'importe quel fichier du référentiel. Il s'agit d'un processus déclaratif.
VonC
1
@donquixote: Je me rends compte que c'est assez ancien mais je ne lis que votre commentaire maintenant. En fait, toutes ces traductions (toute conversion EOL à partir des paramètres eol = ou autocrlf, et des filtres "propres") sont exécutées lorsque les fichiers passent de l'arborescence de travail à l'index, c'est-à-dire pendant git addplutôt qu'à l' git commitheure. (Notez que git commit -aou --onlyou --includefaire des fichiers add à l'index à ce moment - là, cependant.) Pour ce que ça vaut la peine, vous et moi , et Linus Torvalds tout déteste l'idée d'un VCS jamais modifier ce qui est commis. Mais il y a tous ces utilisateurs de Windows ... :-)
torek
34

core.autocrlfla valeur ne dépend pas du type de système d'exploitation mais de la valeur par défaut de Windows est trueet pour Linux - input. J'ai exploré 3 valeurs possibles pour les cas de validation et d'extraction et voici le tableau résultant:

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║
║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║
║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
pratt
la source
5
Bref résumé en mots: les fichiers avec CRseuls ne sont jamais touchés. falsene touche jamais les fins de ligne. truevalide toujours en tant que LFet vérifie en tant que CRLF. Et inputs'engage toujours tel quel LFet vérifie tel quel.
Furkan Kambay
7

Voici ma compréhension jusqu'à présent, au cas où cela aiderait quelqu'un.

core.autocrlf=true et core.safecrlf = true

Vous avez un référentiel où toutes les fins de ligne sont les mêmes , mais vous travaillez sur différentes plateformes. Git s'assurera que les terminaisons de vos lignes sont converties à la valeur par défaut pour votre plate-forme. Pourquoi est-ce important? Disons que vous créez un nouveau fichier. L'éditeur de texte sur votre plateforme utilisera ses fins de ligne par défaut. Lorsque vous l'archivez, si core.autocrlf n'est pas défini sur true, vous avez introduit une incohérence de fin de ligne pour quelqu'un sur une plate-forme qui prend par défaut une fin de ligne différente. Je mets toujours safecrlf aussi parce que je voudrais savoir que l'opération crlf est réversible. Avec ces deux paramètres, git modifie vos fichiers, mais il vérifie que les modifications sont réversibles .

core.autocrlf=false

Vous avez un référentiel qui a déjà des fins de ligne mixtes archivées et la correction des fins de ligne incorrectes pourrait casser d'autres choses. Il est préférable de ne pas dire à git de convertir les fins de ligne dans ce cas, car cela aggravera le problème qu'il a été conçu pour résoudre - rendant les différences plus faciles à lire et fusionnant moins douloureuses. Avec ce paramètre, git ne modifie pas vos fichiers .

core.autocrlf=input

Je ne l'utilise pas parce que la raison en est de couvrir un cas d'utilisation où vous avez créé un fichier qui a des fins de ligne CRLF sur une plate-forme qui par défaut est des fins de ligne LF. Je préfère plutôt que mon éditeur de texte enregistre toujours les nouveaux fichiers avec les valeurs par défaut de fin de ligne de la plate-forme.

Carl
la source
3

Non, la réponse @jmlane est fausse.

Pour Checkin (git add, git commit):

  1. si la textpropriété estSet, Set value to 'auto' , la conversion se produit enen le fichier a été validé avec 'CRLF'
  2. si la textpropriété estUnset : rien ne se passe, enen pourCheckout
  3. si la textpropriété est Unspecified, la conversion dépend decore.autocrlf
    1. si autocrlf = input or autocrlf = true , la conversion ne se produit que lorsque le fichier dans le référentiel est «LF», s'il a été «CRLF», rien ne se passera.
    2. si autocrlf = falserien ne se passe

Pour Checkout:

  1. si la textpropriété estUnset : rien ne se passe.
  2. si la textpropriété est Set, Set value to 'auto: cela dépend core.autocrlf,core.eol .
    1. core.autocrlf = entrée: rien ne se passe
    2. core.autocrlf = true: la conversion ne se produit que lorsque le fichier dans le référentiel est 'LF', 'LF' -> 'CRLF'
    3. core.autocrlf = false: la conversion ne se produit que lorsque le fichier dans le référentiel est 'LF', 'LF' -> core.eol
  3. si la textpropriété est Unspecified, cela dépend core.autocrlf.
    1. le même que 2.1
    2. le même que 2.2
    3. Aucun, rien ne se passe, core.eol n'est pas efficace lorsque la textpropriété estUnspecified

Comportement par défaut

Ainsi, le comportement par défaut est la textpropriété est Unspecifiedet core.autocrlf = false:

  1. pour l'enregistrement, rien ne se passe
  2. pour la caisse, rien ne se passe

Conclusions

  1. si la textpropriété est définie, le comportement d'archivage dépend de lui-même, pas de autocrlf
  2. autocrlf ou core.eol est pour le comportement de paiement, et autocrlf> core.eol
ViciOs
la source
2

A fait quelques tests sur Linux et Windows. J'utilise un fichier de test contenant des lignes se terminant par LF et également des lignes se terminant par CRLF.
Le fichier est validé, supprimé puis extrait. La valeur de core.autocrlf est définie avant la validation et également avant le retrait. Le résultat est ci-dessous.

commit core.autocrlf false, remove, checkout core.autocrlf false: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf input: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf true : LF=>LF   CRLF=>CRLF  
commit core.autocrlf input, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
commit core.autocrlf true, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf true, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf true,  remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
Luc Depoorter
la source