Pourquoi devrais-je utiliser core.autocrlf = true dans Git?

296

J'ai un référentiel Git accessible à partir de Windows et OS X, et que je sais contient déjà certains fichiers avec des fins de ligne CRLF. Autant que je sache, il y a deux façons de gérer cela:

  1. Mis core.autocrlfà falsepartout,

  2. Suivez les instructions ici (écho sur les pages d'aide GitHub) pour convertir le référentiel pour ne contenir que de fins de ligne LF, et mis ensuite core.autocrlfà truesous Windows et inputsous Mac OS X. Le problème avec cela est que si j'ai des fichiers binaires dans le référentiel cette:

    1. ne sont pas correctement marqués comme binaires dans gitattributes, et
    2. arriver à contenir à la fois CRLF et LF,

    ils seront corrompus. Il est possible que mon référentiel contienne de tels fichiers.

Alors pourquoi ne devrais-je pas simplement désactiver la conversion de fin de ligne de Git? Il existe de nombreux avertissements vagues sur le Web concernant la core.autocrlfdésactivation causant des problèmes, mais très peu de problèmes spécifiques ; le seul que j'ai trouvé jusqu'à présent est que kdiff3 ne peut pas gérer les terminaisons CRLF (pas un problème pour moi), et que certains éditeurs de texte ont des problèmes de fin de ligne (également pas un problème pour moi).

Le référentiel est interne à mon entreprise et je n'ai donc pas à me soucier de le partager avec des personnes ayant des paramètres d'autocrlf différents ou des exigences de fin de ligne.

Y a-t-il d'autres problèmes avec le fait de laisser les terminaisons de ligne telles quelles que je ne connais pas?

Riches
la source
1
Est-ce que stackoverflow.com/questions/2333424/… aiderait? J'ai un lien vers des raisons spécifiques pour laisser autocrlfà faux.
VonC
3
@VonC Merci, mais je suis déjà en mesure de dicter que tous les utilisateurs de l'entreprise définissent <code> autocrlf </code> sur false et pensent actuellement que c'est la meilleure option. Mais je veux savoir s'il y a des raisons pour lesquelles je ne devrais pas faire cela, parce que je peux trouver qu'il y a beaucoup de gens (par exemple GitHub) qui disent que j'autocrlf devrait être défini mais pas de détails réels sur pourquoi.
Rich
3
@VonC c'est-à-dire que je ne cherche pas de raisons de mettre autocrlfà faux. Je cherche des raisons pour que ce soit vrai.
Rich
9
Pourquoi ne pas l'utiliser autocrlf = input: cela semble être la résolution parfaite entre les deux extrêmes: vous gardez votre dépôt propre de la merde CRLF, et les développeurs Windows localement peuvent utiliser tout ce qu'ils veulent sans que leurs fichiers locaux n'aient quelque chose de magique qui leur soit fait automatiquement. (Ils peuvent vouloir LF localement pour diverses raisons, donc truec'est mauvais, à mon avis.) Je ne vois aucun inconvénient à utiliser autocrlf = input.
iconoclaste du
7
@iconclast, l'une des raisons pour lesquelles j'ai rencontré un problème est que vous créez des distributions qui incluent à la fois des fichiers batch Windows et des scripts shell Unix. Vous voulez utiliser la ligne correcte se terminant dans chaque cas, et c'est plus difficile à faire si Git fait tourner les choses même après que vous les ayez explicitement définies dans un sens ou dans l'autre.
user1809090

Réponses:

227

Les raisons que précises dictant autocrlfà truesont:

  • évitez d' git statusafficher tous vos fichiers en modifiedraison de la conversion EOL automatique effectuée lors du clonage d'un référentiel EOL Git basé sur Unix vers un fichier Windows (voir le problème 83 par exemple)
  • et vos outils de codage dépendent en quelque sorte d'un style EOL natif présent dans votre fichier:

À moins que vous ne puissiez voir un traitement spécifique qui doit traiter la fin de vie native, vous feriez mieux de partir autocrlfpourfalse ( git config --global core.autocrlf false).

Notez que cette configuration serait locale (car la configuration n'est pas poussée de repo à repo)

Si vous voulez la même configuration pour tous les utilisateurs clonant ce référentiel, consultez " Quelle est la meilleure CRLFstratégie de gestion avec git? ", En utilisant l' textattribut dans le .gitattributesfichier .

Exemple:

*.vcproj    text eol=crlf
*.sh        text eol=lf

Remarque: à partir de git 2.8 (mars 2016), les marqueurs de fusion n'introduiront plus de fin de ligne mixte (LF) dans un fichier CRLF.
Voir " Faire en sorte que Git utilise CRLF sur ses lignes de fusion" <<<<<<< HEAD " "

VonC
la source
5
@VonC Merci! Cela m'aide à me sentir plus confiant que je peux l'utiliser sans danger autocrlf=false. Par intérêt, savez-vous pourquoi git effectue toujours la conversion eol même si autocrlf est défini sur false?
Rich
14
@VonC: Je ne pense pas que cette réponse soit correcte. L'utilisation de core.autocrlf = true sous Windows fonctionne comme prévu. Tous les fichiers du référentiel (qui devraient avoir des fins de ligne LF dans ce scénario) sont convertis en fins de ligne CRLF lors du paiement sur un PC Windows. Tous les fichiers sont reconvertis en fins de ligne LF lors de la validation à partir d'un PC Windows. Le moyen d'avoir des ennuis est de passer d'abord à un PC Windows avec le mauvais paramètre core.autocrlf (ce qui est tout à fait trop facile à faire).
Michael Maddox
3
@Michael Dans ce cas, est-ce que la seule raison de ne pas utiliser core.autocrlf=falsedans mon scénario serait d'avoir un outil / éditeur qui serait confus par les fins de ligne?
Rich
49
J'utiliserais certainement false, je n'ai jamais été un grand fan de choses automatiques ou magiques qui se passent en arrière-plan. Utilisez simplement \net UTF-8partout et tout ira bien. Si un crétin ne comprend pas qu'il existe des conventions et des règles et oublie d'utiliser UTF-8ou \n, alors quelqu'un les convertit manuellement et lui gifle le visage.
Tour
5
@ Pauld'Aoust Je préférerais quand même spécifier le type de fichier nécessitant ce CRLF via des core.eolattributs dans un .gitattributesfichier, plutôt que d'utiliser ce core.autocrlfparamètre global qui s'applique sans discrimination à tous les fichiers.
VonC
40

Je suis un développeur .NET et j'utilise Git et Visual Studio depuis des années. Ma recommandation forte est de définir les fins de ligne sur true. Et faites-le le plus tôt possible pendant la durée de vie de votre référentiel.

Cela étant dit, je DÉTESTE que Git change mes fins de ligne. Un contrôle de code source doit uniquement enregistrer et récupérer le travail que je fais, il ne doit PAS le modifier. Déjà. Mais c'est le cas.

Que se passera-t-il si tous les développeurs ne sont pas définis sur true, si UN développeur finira par être défini sur true. Cela commencera à changer les fins de ligne de tous vos fichiers en LF dans votre référentiel. Et lorsque les utilisateurs définissent de fausses vérifications, Visual Studio vous avertit et vous demande de les modifier. Vous aurez 2 choses très rapidement. Premièrement, vous obtiendrez de plus en plus de ces avertissements, plus votre équipe sera grande, plus vous en aurez. La seconde, et pire, est que cela montrera que chaque ligne de chaque fichier modifié a été modifiée (car les fins de ligne de chaque ligne seront modifiées par le vrai gars). Finalement, vous ne pourrez plus suivre de manière fiable les modifications de votre référentiel. Il est BEAUCOUP plus facile et plus propre de faire en sorte que tout le monde reste fidèle que d'essayer de garder tout le monde faux. Aussi horrible que de vivre avec le fait que votre contrôle de source de confiance fait quelque chose qu'il ne devrait pas faire. Déjà.

JGTaylor
la source
Mon entreprise est suffisamment petite pour que nous puissions facilement exiger que false soit utilisé partout, et j'aurais pensé que les grandes entreprises pourraient le faire via une politique, mais je suppose que c'est une raison légitime d'utiliser "true", donc je vote de manière positive en tous cas. Merci!
Rich
1
Le problème avec cette stratégie (fichier appliqué) est que sur une machine Windows, vous pouvez avoir un fichier de configuration local, global et caché (ProgramData / Git / Confg). Vous pouvez appliquer le local en le consignant dans le référentiel, mais le Global ET les fichiers cachés ont priorité. Il est également possible de faire en sorte que local et global (ou caché) soient différents. S'ils le sont, ils entreront en conflit les uns avec les autres sur la même machine, provoquant des erreurs de fin de ligne là où il n'y en a pas. C'est une douleur à retrouver. :(
JGTaylor
7
exactement ce que je pense. ce n'est pas le travail d'un contrôle de code source de jouer avec les fichiers de code à sa guise. les fins de ligne ne devraient être qu'une préoccupation des outils d'édition, rien de plus.
Tuncay Göncüoğlu
6
Si votre projet est uniquement Windows, il n'y a aucun problème. Cependant, si vous ou vos collègues travaillez sur une plate-forme * nix, votre "recommandation forte" posera des problèmes. Essayez d'exécuter un script bash, perl ou python avec le shebang se terminant par \r\net vous verrez.
phuclv
6
La situation que vous avez décrite n'est pas un problème de GIT, définissez le paramètre sur FALSE comme il devrait normalement être et c'est parti. Instad, c'est un problème dans le travail d'équipe. Qu'est-ce que cela signifie "éventuellement un développeur définit true"? Pourquoi leur permettriez-vous cela en premier lieu? lorsque vous les configurez pour accéder à git repo, alors tout comme vous ne permettez pas de polluer certaines zones avec des langages différents (donc toute personne qui y travaille peut le lire), ou tout comme vous gardez des branches / fusions / rebases / etc le long du chemin choisi la politique, ils devraient obtenir une règle claire: définissez le crlf correct.
quetzalcoatl
12

Mise à jour 2 :

Xcode 9 semble avoir une "fonctionnalité" où il ignorera les fins de ligne actuelles du fichier et utilisera simplement votre paramètre de fin de ligne par défaut lors de l'insertion de lignes dans un fichier, ce qui entraîne des fichiers avec des fins de ligne mixtes.

Je suis presque sûr que ce bogue n'existait pas dans Xcode 7; pas sûr de Xcode 8. La bonne nouvelle est qu'il semble être corrigé dans Xcode 10.

Pour le moment où il existait, ce bug a provoqué une petite hilarité dans la base de code à laquelle je fais référence dans la question (qui à ce jour utilise autocrlf=false), et a conduit à de nombreux messages de validation "EOL" et finalement à mon écriture un pre-commitcrochet git pour vérifier pour / empêcher l'introduction de fins de ligne mixtes.

Mise à jour :

Note: Comme indiqué par VonC, à partir de Git 2.8, les marqueurs de fusion ne pas introduire de fins de ligne de style Unix dans un fichier de type Windows .

Original :

Un petit hoquet que j'ai remarqué avec cette configuration est que lorsqu'il y a des conflits de fusion, les lignes que git ajoute pour marquer les différences n'ont pas de fins de ligne Windows, même lorsque le reste du fichier en a, et vous pouvez finir avec un fichier avec des fins de ligne mixtes, par exemple:

// Some code<CR><LF>
<<<<<<< Updated upstream<LF>
// Change A<CR><LF>
=======<LF>
// Change B<CR><LF>
>>>>>>> Stashed changes<LF>
// More code<CR><LF>

Cela ne nous pose aucun problème (j'imagine que tout outil capable de gérer les deux types de fins de ligne traitera également les fins de ligne mixtes - certainement toutes celles que nous utilisons), mais c'est quelque chose dont il faut être conscient.

L'autre chose * que nous avons trouvée, c'est que lors de l'utilisation git diffpour afficher les modifications d'un fichier qui a des fins de ligne Windows, les lignes qui ont été ajoutées affichent leurs retours chariot, ainsi:

    // Not changed

+   // New line added in^M
+^M
    // Not changed
    // Not changed

* Il ne mérite pas vraiment le terme: "issue".

Riches
la source
2
NB Lorsque Visual Studio rencontre un tel fichier, il propose de normaliser les fins de ligne pour vous. Choisir des fins de ligne Windows ou choisir de ne pas normaliser les fins de ligne fonctionne très bien (comme VS l'affiche toujours correctement, les lignes incriminées auront été supprimées une fois le conflit résolu).
Rich
2
Malheureusement, les nazis de contrôle de version d'entreprise ne sont pas d'accord avec cela (LF sur les marqueurs de conflit de fusion) n'étant pas un problème.
Ilia G
1
Je suis d'accord que LF sur les marqueurs de conflit de fusion ne devrait pas être un problème. Ces lignes ne devraient pas être engagées de toute façon.
voler
1
Remarque: à partir de git 2.8 (mars 2016), les marqueurs de fusion auront en fait une fin de ligne CRLF. Voir stackoverflow.com/a/35474954/6309
VonC