Quelle est la meilleure stratégie de traitement de CRLF (retour chariot, saut de ligne) avec Git?
-
05-07-2019 - |
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.
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ètrecore.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 oucore.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 decore.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’optioncore.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.
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 ligneLF
. Aucun danger pour le reste de l'équipe, car vos commits seront toujours normalisés avec des fins de ligneLF
. - Si vous êtes un utilisateur Windows avec
core.autocrlf = false
, vous verrez un tas de fichiers avec des fins de ligneLF
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 terminaisonsCRLF
, probablement des utilisateurs Windows dotés decore.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
-
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 "
-
Convertissez tous les fichiers modifiés au format DOS:
unix2dos $(git lc)
-
Facultativement ...
-
Créez un crochet pour cela action pour automatiser ce processus
-
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)" | ...
-
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.
windows/linux clients:
core.autocrlf=input
committed
.gitattributes
:* text=auto eol=lf
committed
.editorconfig
(http://editorconfig.org/) which is kind of standardized format, combined with editor plugins:
--- 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 throughgit-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