web-dev-qa-db-fra.com

Comment les conversions de fin de ligne fonctionnent-elles avec git core.autocrlf entre différents systèmes d'exploitation

J'ai lu de nombreuses questions et réponses sur le dépassement de capacité, ainsi que de la documentation de Git sur la manière dont le noyau Le paramètre .autocrlf fonctionne.

Voici ce que j'ai compris de ce que j'ai lu:

Unix et Mac OSX (les utilisateurs de logiciels utilisant la version antérieure à OSX) utilisent des terminaisons de ligne LF).
Les clients Windows utilisent les fins de ligne CRLF.

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

Voici une matrice qui tente de documenter la même chose pour les paramètres 'input' et 'false' de core.autocrlf avec des points d'interrogation pour lesquels 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 "points d'interrogation"?

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

 core.autocrlf value 
 true entrée false 
 -------------------------------- ------------------------------ 
 commit | convertir? ? 
 nouveau | to LF (convertir en LF?) (pas de conversion?) 
 
 commit | convertir en? no 
 existant | LF (convertir en LF?) Conversion 
 
 Commander | convertir en? Non 
 Existant | CRLF (pas de conversion?) Conversion 
 

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

-

Mise à jour du 17/04/2012 : Après avoir lu l'article de Tim Clem lié par JJD dans les commentaires, j'en ai modifié quelques-uns des valeurs dans les valeurs "inconnues" dans le tableau ci-dessus, ainsi que la modification de "extraction existante | 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. L'utilisation de false a pour résultat que Git ne gâche 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 logiciels et que Git s'en moque. Cela peut rendre les diffs plus difficiles à lire et les fusions plus difficiles. La plupart des Le monde Unix/Linux utilise 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 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 objet) et reconvertira tous LF en CRLF lors de l'écriture dans le répertoire de travail (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 = input

Cela signifie que Git traitera tous les fichiers texte et veillera à ce que CRLF soit remplacé par LF lors de l'écriture de ce fichier dans la base de données objet. Il ne fera toutefois pas l'inverse. Lorsque vous lisez des fichiers pour sortir de la base de données d'objets et les écrire 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é sous Unix/Linux/OS X pour empêcher les CRLF d'être écrits dans le référentiel. que si vous avez collé du code à partir d'un navigateur Web et que des CRLF ont été accidentellement insérés dans l'un de vos fichiers, Git devrait s'assurer qu'ils ont été remplacés par des LF lorsque vous avez écrit dans la base de données d'objets.

L'article de Tim est excellent, la seule chose qui me 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 uniquement Windows.

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.

200
Michael Maddox

La meilleure explication de la façon dont core.autocrlf _ travaux se trouve sur la page de manuel gitattributes , dans la section attribut text.

C'est ainsi core.autocrlf semble fonctionner actuellement (ou du moins depuis la version 1.7.2, à ma connaissance):

  • core.autocrlf = true
    1. Les fichiers texte extraits du référentiel contenant uniquement LF caractères sont normalisés en CRLF dans votre arbre de travail; les fichiers contenant CRLF dans le référentiel ne seront pas touchés
    2. Les fichiers texte ne contenant que LF caractères dans le référentiel sont normalisés de CRLF à LF lorsqu’ils ont été renvoyés dans le référentiel. Les fichiers contenant CRLF dans le référentiel seront validés.
  • core.autocrlf = input
    1. Les fichiers texte extraits du référentiel conserveront les caractères EOL originaux dans votre arborescence de travail.
    2. Les fichiers texte de votre arbre de travail comportant des caractères CRLF sont normalisés à LF lorsqu'ils sont renvoyés au référentiel.
  • core.autocrlf = false
    1. core.eol dicte les caractères EOL dans les fichiers texte de votre arbre de travail.
    2. core.eol = native par défaut, ce qui signifie que les EOL Windows sont CRLF et * nix. Les EOL sont LF dans les arborescences actives.
    3. Les paramètres du référentiel gitattributes déterminent la normalisation des caractères EOL pour les validations dans le référentiel (la normalisation par défaut est définie sur LF caractères).

Je viens tout juste de faire une recherche sur ce problème et je trouve également que la situation est très compliquée. Le core.eol le réglage a clairement aidé à clarifier la manière dont les caractères EOL sont gérés par git.

119
jmlane

La question des EOL dans les projets à plates-formes mixtes me rend la vie misérable depuis longtemps. Les problèmes surviennent généralement lorsqu'il existe déjà des fichiers contenant des fichiers EOL différents et mélangés déjà dans le référentiel. Cela signifie que:

  1. Le repo peut avoir différents fichiers avec différents EOL
  2. Certains fichiers du référentiel peuvent avoir mélangé EOL, par exemple. une combinaison de CRLF et LF dans 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 sous Windows pour les différents modes et leurs combinaisons.
Voici ce que j’ai eu, dans un tableau légèrement modifié:

 | Conversion résultant lorsque | Conversion résultante lorsque 
 | commettre des fichiers avec divers | vérifier de repo - 
 | EOLs en repo et | avec des fichiers mélangés dedans et 
 | valeur core.autocrlf: | valeur core.autocrlf: 
 -------------------------------------------- ---------------------------------------- 
 Fichier | vrai | entrée | faux | vrai | entrée | faux
-------------------------------------------- ------------------------------------ 
 Windows-CRLF | CRLF -> LF | CRLF -> LF | tel quel | tel quel | tel quel | tel que. | 
 Unix - LF | tel quel | tel quel | tel quel | LF -> CRLF | tel quel | tel quel 
 Mac -CR | tel quel | as- est | tel quel | tel quel | tel quel | tel quel 
 CRLF mixte + LF | tel quel | tel quel | tel quel | tel quel | tel quel | tel quel is 
 Mixed-CRLF + LF + CR | tel quel | tel quel | tel quel | tel quel | tel quel | tel quel | tel quel 
 

Comme vous pouvez le constater, il existe 2 cas de conversion lors de la validation (3 colonnes de gauche). Dans le reste des cas, les fichiers sont validés tels quels.

Au moment du paiement (3 colonnes de droite), il n’ya qu'un seul cas où la conversion se produit lorsque:

  1. core.autocrlf est trueet
  2. le fichier dans le référentiel a le LF EOL.

Le plus surprenant pour moi, et je suppose, la cause de nombreux problèmes EOL est qu’il n’existe pas de configuration dans laquelle les EOL mixtes comme CRLF + LF soient normalisées.

Notez également que les "anciens" EOLs Mac de CR ne sont jamais convertis.
Cela signifie que si un script de conversion EOL mal écrit tente de convertir un fichier de terminaison mixte avec CRLFs + LFs, il suffit de convertir LFs en CRLFs, il laissera le fichier en mode mixte avec "lonely" CRs chaque fois qu'un CRLF a été converti en CRCRLF.
Git ne convertira alors rien, même en mode true, et le chaos EOL continue. C’est ce qui m’est vraiment arrivé et j’ai vraiment mal gaché mes fichiers, car certains éditeurs et compilateurs (par exemple, VS2010) n’aiment pas les EOL pour Mac.

Je suppose que la seule façon de vraiment gérer ces problèmes est de occasionnellement normaliser le référentiel entier en extrayant tous les fichiers en mode input ou false, en effectuant une normalisation appropriée et ré-enregistrer les fichiers modifiés (le cas échéant). Sous Windows, probablement continuer à travailler avec core.autocrlf true.

57
Adi Shavit

Les choses sont sur le point de changer sur le front de la "conversion eol", avec le prochain Git 1.7.2 :

Un nouveau paramètre de configuration core.eol _ est en train d’être ajouté/évolué :

Ceci remplace le "Ajouter" core.eol "variable de configuration 'commit actuellement dans pu (le dernier de ma série).
Au lieu de laisser entendre que "core.autocrlf=true "remplace le" * text=auto ", explicite le fait que autocrlf ne s’adresse qu'aux utilisateurs qui souhaitent utiliser des CRLF dans leur répertoire de travail sur un référentiel ne disposant 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.
La valeur par défaut est "native", ce qui signifie CRLF sous 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 si core.eol est réglé sur "lf".

core.eol:

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


Autres évolutions sont à l'étude :

Pour 1.8, je penserais à faire core.autocrlf il suffit d’activer la normalisation et de laisser la décision de clôture de la ligne du répertoire de travail à core.eol, mais cela le sera rompt la configuration des utilisateurs.


git 2.8 (mars 2016) améliore le chemin core.autocrlf _ influence l’EOL:

Voir commit 817a0c7 (23 février 2016), commit 6e336a5 , commit df747b8 , commit df747b8 (10 février 2016) , commit df747b8 , commit df747b8 (10 fév 2016), et commit 4b4024f , commit bb211b4 , commit 92cce1 , commit 320d39c , commit 4b4024f , commit bb211b4 , commit 92cce1 , commit 320d39c (05 fév 2016) par Torsten Bögershausen (tboegi) .
(Fusion par Junio ​​C Hamano - gitster - dans commit c6b94eb , 26 février 2016)

convert.c: refactor crlf_action

Refactoriser la détermination et l'utilisation de crlf_action.
Aujourd'hui, quand aucun attribut "crlf" n'est défini sur un fichier, crlf_action est réglé sur CRLF_GUESS. Utilisation CRLF_UNDEFINED à la place et recherchez "text" ou "eol" comme auparavant.

Remplacez l'ancien CRLF_GUESS _ utilisation:

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

Rendre plus clair, qu'est-ce que c'est, 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 torek ajoute dans les commentaires :

toutes ces traductions (toute conversion EOL de eol= ou autocrlf paramètres et les filtres "clean") sont exécutés lorsque les fichiers passent de l’arbre de travail à l’index , c'est-à-dire pendant git add plutôt que chez git commit temps.
(Notez que git commit -a ou --only ou --include ajoute cependant des fichiers à l’index à ce moment-là.)

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

38
VonC

core.autocrlf La valeur ne dépend pas du type de système d'exploitation, mais sous Windows, la valeur par défaut est true et pour Linux, input. J'ai exploré 3 valeurs possibles pour les cas de validation et de validation et voici le tableau obtenu:

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ 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 ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
28
pratt

Voici ce que j'ai compris jusqu'ici, 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 des plateformes différentes. Git s'assurera que vos fins de lignes sont converties en valeurs par défaut pour votre plate-forme. Pourquoi est-ce important? Disons que vous créez un nouveau fichier. L'éditeur de texte de votre plate-forme utilisera ses fins de ligne par défaut. Lorsque vous l'enregistrez, si core.autocrlf n'est pas défini sur true, vous avez introduit une incohérence à la fin de la ligne pour une personne sur une plate-forme qui utilise par défaut une fin de ligne différente. Je mets toujours aussi safecrlf parce que j'aimerais 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 le référentiel qui a déjà des fins de ligne mixtes est archivé et la correction des fins de ligne incorrectes peut entraîner des problèmes. Dans ce cas, il est préférable de ne pas demander à git de convertir les fins de ligne, car cela aggravera le problème pour lequel il a été conçu - ce qui rend les différences plus faciles à lire et les fusions moins pénibles. Avec ce réglage, git ne modifie pas vos fichiers.

core.autocrlf=input

Je n’utilise pas cela car la raison en est de couvrir un cas d’utilisation dans lequel vous avez créé un fichier avec des fins de ligne CRLF sur une plate-forme dont la valeur par défaut est LF fins de ligne. Je préfère plutôt oblige mon éditeur de texte à toujours sauvegarder les nouveaux fichiers avec les valeurs par défaut de la fin de ligne de la plate-forme.

6
Carl

Non, la réponse @jmlane est fausse.

Pour Checkin (git add, git commit):

  1. si text la propriété est Set, Set value to 'auto', la conversion se produit lorsque le fichier a été validé avec 'CRLF'
  2. si la propriété text est Unset: rien ne se passe, enen pour Checkout
  3. si la propriété text est Unspecified, la conversion dépend de core.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 déjà été 'CRLF', rien ne se passera.
    2. si autocrlf = false, Rien ne se passe

Pour Checkout:

  1. si la propriété text est Unset: rien ne se passe.
  2. si text la propriété est Set, Set value to 'auto: ça dépend de core.autocrlf, core.eol.
    1. core.autocrlf = input: rien ne se passe
    2. core.autocrlf = true: la conversion n'a lieu 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 du référentiel est 'LF', 'LF' -> core.eol
  3. si la propriété text est Unspecified, elle dépend de core.autocrlf.
    1. le même que 2.1
    2. le même que 2.2
    3. Aucune, rien ne se passe, core.eol n'est pas efficace lorsque la propriété text est Unspecified

Comportement par défaut

Donc, le comportement par défaut est text la propriété est Unspecified et core.autocrlf = false:

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

Conclusions

  1. si la propriété text est définie, le comportement d’archivage dépend de lui-même et non d’autocrlf.
  2. autocrlf ou core.eol est destiné au comportement de paiement, et autocrlf> core.eol
2
ViciOs

A fait des tests à la fois sur Linux et Windows. J'utilise un fichier de test contenant des lignes se terminant par LF) ainsi que 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 paiement. 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  
2
Luc Depoorter