Quelle est la meilleure stratégie de traitement de CRLF (retour chariot, saut de ligne) avec Git?

StackOverflow https://stackoverflow.com/questions/170961

Question

J'ai essayé de valider des fichiers avec des lignes de fin CRLF, mais cela a échoué.

J'ai passé toute une journée de travail sur mon ordinateur Windows à essayer différentes stratégies. J'étais presque incité à cesser d'utiliser Git et à essayer plutôt Mercurial .

Ne partagez qu'une seule bonne pratique par réponse.

Était-ce utile?

La solution

Près de quatre ans après avoir posé cette question, j'ai enfin trouvé une réponse qui me satisfait complètement !

Voir les détails dans le github: aide du Guide de Gestion des fins de ligne .

  

Git vous permet de définir les propriétés de fin de ligne pour un   repo directement en utilisant l'attribut text dans le    .gitattributes . Ce fichier est engagé dans   le repo et remplace le paramètre core.autocrlf ,   vous permettant d'assurer un comportement cohérent pour tous   les utilisateurs indépendamment de leurs paramètres git.

Et ainsi

  

L’avantage de ceci est que votre fin de ligne   configuration se déplace maintenant avec votre référentiel et vous   pas besoin de s'inquiéter de savoir si ou non des collaborateurs   avoir les paramètres globaux appropriés.

Voici un exemple de fichier .gitattributes

# Auto detect text files and perform LF normalization
*        text=auto

*.cs     text diff=csharp
*.java   text diff=java
*.html   text diff=html
*.css    text
*.js     text
*.sql    text

*.csproj text merge=union
*.sln    text merge=union eol=crlf

*.docx   diff=astextplain
*.DOCX   diff=astextplain

# absolute paths are ok, as are globs
/**/postinst* text eol=lf

# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf

Il existe une collection de fichiers .gitattributes prêts à être utilisés pour les langages de programmation les plus courants. C'est utile pour commencer.

Une fois que vous avez créé ou ajusté votre .gitattributes , vous devez exécuter une normalisation des fins de ligne .

Notez que l'application GitHub Desktop peut suggérer et créer un .gitattributes . fichier après avoir ouvert le dépôt Git de votre projet dans l'application. Pour essayer, cliquez sur l'icône représentant une roue dentée (dans le coin supérieur droit) > Paramètres du référentiel ... > Terminaisons et attributs. Vous serez invité à ajouter le .gitattributes recommandé. Si vous acceptez, l'application procédera également à une normalisation de tous les fichiers de votre référentiel.

Enfin, l'article Attention à la fin de votre ligne fournit plus de contexte et explique comment Git a évolué sur les questions à l'ordre du jour. Je considère cette lecture obligatoire .

Vous avez probablement des utilisateurs de votre équipe qui utilisent EGit ou JGit (des outils tels que Eclipse et TeamCity les utilisent) pour valider leurs modifications. Alors vous n'avez pas de chance, comme l'explique @gatinueta dans les commentaires de cette réponse:

  

Ce paramètre ne vous satisfera pas complètement si vous avez des personnes travaillant avec Egit ou JGit dans votre équipe, car ces outils ignoreront simplement .gitattributes et archiveront les fichiers CRLF https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372

Une astuce pourrait consister à demander aux utilisateurs de valider leurs modifications dans un autre client, par exemple SourceTree . Notre équipe à l'époque préférait cet outil à l'Egit d'Eclipse pour de nombreux cas d'utilisation.

Qui a dit qu'un logiciel est facile? : - /

Autres conseils

Ne convertissez pas les fins de ligne. Ce n’est pas à VCS d’interpréter les données, mais de les stocker et de les mettre en version. Tout éditeur de texte moderne peut lire les deux types de fin de ligne.

Vous voulez presque toujours autocrlf = input sauf si vous savez vraiment ce que vous faites.

Un contexte supplémentaire ci-dessous:

  

Cela devrait être core.autocrlf = true si vous aimez   Terminaison DOS ou core.autocrlf = entrée si vous préférez   unix-newlines. Dans les deux cas, votre référentiel Git sera   avoir seulement LF, qui est la bonne chose. Le seul   l'argument de core.autocrlf = false était automatique   l'heuristique peut détecter de manière incorrecte certains binaires en tant que texte   et alors votre tuile sera corrompue. Alors,   L’option core.safecrlf a été introduite pour avertir un utilisateur si   un changement irréversible se produit. En fait, il y a deux   possibilités de changements irréversibles - mixtes   la ligne se terminant dans un fichier texte, dans cette normalisation est   souhaitable, donc cet avertissement peut être ignoré, ou   (très peu probable) que Git ait mal détecté votre   fichier binaire sous forme de texte. Ensuite, vous devez utiliser des attributs pour   dit à Git que ce fichier est binaire.

Le paragraphe ci-dessus a été extrait d'un fil de discussion sur gmane.org, mais il est depuis tombé.

Deux stratégies alternatives pour devenir cohérent concernant les fins de ligne dans des environnements mixtes (Microsoft + Linux + Mac):

A. par configuration de tous les référentiels

1) Convertissez le tout dans un seul format

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

2) Définissez core.autocrlf sur entrée sous Linux / UNIX ou true sur MS Windows (référentiel ou global)

git config --global core.autocrlf input

3) [Facultatif] définissez core.safecrlf sur true (arrêter) ou avertir (chanter :) pour ajouter une protection supplémentaire comparer si la transformation de nouvelle ligne inversée aboutit au même fichier

git config --global core.safecrlf true


B. Ou par configuration de référentiel

1) Convertissez le tout dans un seul format

echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'

2) ajoutez le fichier .gitattributes à votre référentiel

<*>

Ne vous inquiétez pas pour vos fichiers binaires - Git devrait être assez intelligent à leur sujet.

En savoir plus sur les variables safecrlf / autocrlf

Essayez de définir l'option de configuration core.autocrlf sur true . Regardez également l’option core.safecrlf .

En fait, il semble que core.safecrlf ait peut-être déjà été défini dans votre référentiel, car (souligné par moi):

  

Si ce n'est pas le cas pour le paramètre actuel de core.autocrlf, git rejettera le fichier .

Si tel est le cas, vous pouvez vérifier que votre éditeur de texte est configuré pour utiliser les fins de ligne de manière cohérente. Vous rencontrerez probablement des problèmes si un fichier texte contient un mélange de fins de lignes LF et CRLF.

Enfin, j’estime que la recommandation consistant à simplement "utiliser ce que vous avez reçu" et utiliser des lignes terminées LF sous Windows causera plus de problèmes qu'il n'en résout. Git dispose des options ci-dessus pour essayer de gérer les fins de ligne de manière judicieuse. Il est donc logique de les utiliser.

L'utilisation de core.autocrlf = false a arrêté la mise à jour de tous les fichiers dès que je les ai archivés dans mon Visual Studio & nbsp; 2010 . Les deux autres membres de l’équipe de développement utilisent également des systèmes Windows. Ainsi, aucun environnement mixte n’est entré en jeu. Cependant, les paramètres par défaut fournis avec le référentiel ont toujours indiqué que tous les fichiers étaient mis à jour immédiatement après le clonage.

Je suppose que le but ultime est de déterminer le paramètre CRLF qui convient à votre environnement. D'autant que dans de nombreux autres référentiels de nos machines Linux, le paramètre autocrlf = true produit de meilleurs résultats.

Plus de 20 ans plus tard, nous avons toujours affaire à des disparités de fin de ligne entre systèmes d’exploitation ... triste.

Ce sont les deux options pour les utilisateurs Windows et Visual Studio qui partagent le code avec des utilisateurs Mac ou Linux . . Pour une explication détaillée, consultez le manuel de gitattributes .

* text = auto

Dans le fichier .gitattributes de votre référentiel, ajoutez:

*   text=auto

Ceci normalisera tous les fichiers avec des fins de ligne LF dans le référentiel.

Et en fonction de votre système d'exploitation (paramètre core.eol ), les fichiers de l'arborescence de travail seront normalisés à LF pour les systèmes Unix ou à CRLF pour les systèmes Windows.

Il s'agit de la configuration utilisée par Microsoft .NET .

Exemple:

Hello\r\nWorld

Sera normalisé dans le repo toujours comme:

Hello\nWorld

Lors du paiement, l’arborescence de travail de Windows sera convertie en:

<*>

À la caisse, l’arborescence de travail sur Mac sera laissée sous la forme: <*>

  

Remarque: si votre référentiel contient déjà des fichiers non normalisés, git status indiquera que ces fichiers sont complètement modifiés la prochaine fois que vous apportez des modifications, et que d'autres utilisateurs risquent fusionner leurs modifications plus tard. Voir rafraîchissement d'un référentiel après avoir changé les fins de ligne pour plus d'informations.

core.autocrlf = true

Si texte n'est pas spécifié dans le fichier .gitattributes , Git utilise la variable de configuration core.autocrlf pour déterminer si le fichier doit être converti. .

Pour les utilisateurs Windows, git config --global core.autocrlf true est une excellente option pour les raisons suivantes:

  • Les fichiers sont normalisés en LF fins de ligne uniquement lorsqu'ils sont ajoutés au référentiel. S'il existe des fichiers non normalisés dans le référentiel, ce paramètre ne les touchera pas.
  • Tous les fichiers texte sont convertis en fins de ligne CRLF dans le répertoire de travail.

Le problème avec cette approche est que:

  • Si vous êtes un utilisateur Windows avec autocrlf = input , vous verrez un tas de fichiers avec des fins de ligne LF . Aucun danger pour le reste de l'équipe, car vos commits seront toujours normalisés avec des fins de ligne LF .
  • Si vous êtes un utilisateur Windows avec core.autocrlf = false , vous verrez un tas de fichiers avec des fins de ligne LF et vous pouvez introduire des fichiers avec . CRLF fins de ligne dans le référentiel.
  • La plupart des utilisateurs Mac utilisent autocrlf = input et peuvent obtenir des fichiers avec des terminaisons CRLF , probablement des utilisateurs Windows dotés de core.autocrlf = false . .

Il ne s'agit que d'une solution de contournement :

Dans des cas normaux, utilisez les solutions fournies avec git. Ceux-ci fonctionnent très bien dans la plupart des cas. Force to LF si vous partagez le développement sur des systèmes Windows et Unix en définissant .gitattributes .

Dans mon cas, il y avait > 10 programmeurs développant un projet sous Windows. Ce projet a été vérifié avec CRLF et il n’existait pas d’option pour forcer la FL.

Certains paramètres ont été écrits en interne sur ma machine sans aucune influence sur le format LF. ainsi, certains fichiers ont été globalement modifiés en LF à chaque changement de fichier.

Ma solution:

Machines Windows: Laissez tout tel quel. Ne vous souciez de rien, car vous êtes un développeur Windows par défaut et vous devez vous en tenir à ceci: "Il n'y a pas d'autre système dans le monde, n'est-ce pas?"

Machines Unix

  1. Ajoutez les lignes suivantes à la section [alias] d'une config. Cette commande répertorie tous les fichiers modifiés (c'est-à-dire modifiés / nouveaux):

    lc = "!f() { git status --porcelain \
                 | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
                 | cut -c 4- ; }; f "
    
  2. Convertissez tous les fichiers modifiés au format DOS:

    unix2dos $(git lc)
    
  3. Facultativement ...

    1. Créez un crochet pour cela action pour automatiser ce processus

    2. Utilisez les paramètres, incluez-les et modifiez la fonction grep pour qu'elle ne corresponde qu'à des noms de fichiers particuliers, par exemple:

      .
      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
      
    3. N'hésitez pas à le rendre encore plus pratique en utilisant un raccourci supplémentaire:

      c2dos = "!f() { unix2dos $(git lc) ; }; f "
      

      ... et déclenchez la conversion en tapant

      git c2dos
      

I have spent hours to come up with the best possible use of .gitattributes, to finally realize, that I cannot count on it.
Unfortunately, as long as JGit-based editors exist (which cannot handle .gitattributes correctly), the safe solution is to force LF everywhere even on editor-level.

Use the following anti-CRLF disinfectants.

--- UPDATE 2 ---

The dafaults of git client will work in most cases. Even if you only have windows only clients, linux only clients or both. These are:

  • windows: core.autocrlf=true means convert lines to CRLF on checkout and convert lines to LF when adding files.
  • linux: core.autocrlf=input means don't convert lines on checkout (no need to since files are expected to be committed with LF) and convert lines to LF (if needed) when adding files.

The property can be set in different scopes. I would suggest explicitly setting in the --global scope, to avoid some IDE issues described at the end.

git config core.autocrlf
git config --global core.autocrlf
git config --system core.autocrlf
git config --local core.autocrlf
git config --show-origin core.autocrlf

Also I would strongly discourage using git config --global core.autocrlf false (in case you have windows only clients) in contrast to what is proposed to git documentation. Setting to false will commit files with CRLF in the repo. But there is really no reason. You never know whether you will need to share the project with linux users. Plus it's one extra step for each client that joins the project instead of using defaults.

Now for some special cases of files (e.g. *.bat *.sh) which you want them to be checked-out with LF or with CRLF you can use .gitattributes

To sum-up for me the best practice is:

  • Make sure that every non-binary file is committed with LF on git repo (default behaviour).
  • Use this command to make sure that no files are committed with CRLF: git grep -I --files-with-matches --perl-regexp '\r' HEAD (Note: on windows clients works only through git-bash and on linux clients only if compiled using --with-libpcre in ./configure).
  • If you find any such files by executing the above command, correct them.
  • Use only the bare minimum .gitattributes
  • Instruct the users to set the core.autocrlf described above to its default values.
  • Do not count 100% on the presence of .gitattributes. git-clients of IDEs may ignore them or treat them differrently.

As said some things can be added in git attributes:

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf

I think some other safe options for .gitattributes instead of using auto-detection for binary files:

  • -text (e.g for *.zip or *.jpg files: Will not be treated as text. Thus no line-ending conversions will be attempted. Diff might be possible through conversion programs)
  • text !eol (e.g. for *.java,*.html: Treated as text, but eol style preference is not set. So client setting is used.)
  • -text -diff -merge (e.g for *.hugefile: Not treated as text. No diff/merge possible)

--- PREVIOUS UPDATE ---

One painful example of a client that will commit files wrongly:

netbeans 8.2 (on windows), will wrongly commit all text files with CRLFs, unless you have explicitly set core.autocrlf as global. This contradicts to the standard git client behaviour, and causes lots of problems later, while updating/merging. This is what makes some files appear different (although they are not) even when you revert.
The same behaviour in netbeans happens even if you have added correct .gitattributes to your project.

Using the following command after a commit, will at least help you detect early whether your git repo has line ending issues: git grep -I --files-with-matches --perl-regexp '\r' HEAD

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top