Force LF eol dans git repo et copie de travail

170

J'ai un dépôt git hébergé sur github. La plupart des fichiers ont été initialement développés sous Windows et je n'ai pas fait trop attention aux fins de ligne. Lorsque j'ai effectué le commit initial, je n'avais pas non plus de configuration git en place pour appliquer les fins de ligne correctes. Le résultat est que j'ai un certain nombre de fichiers avec des fins de ligne CRLF dans mon référentiel github.

Je développe maintenant partiellement sous Linux, et j'aimerais nettoyer les fins de ligne. Comment puis-je m'assurer que les fichiers sont correctement stockés avec LF sur github et que LF est dans ma copie de travail?

J'ai mis en place un .gitattributesfichier contenant text eol=LF; Est-ce exact? Avec cela engagé et poussé, puis-je simplement rmmon dépôt local et re-cloner à partir de github pour obtenir l'effet souhaité?

Chowlett
la source
1
duplication possible de git remplaçant LF par CRLF
Lazy Badger
Ni l'un ni l'autre de ces éléments n'est exactement ce que je demande. Je suis le seul développeur, et je suis tout à fait disposé à configurer toutes mes machines de la même manière. J'ai un référentiel existant avec des fichiers CRLF déjà engagés, et quelques clones sur différentes machines. Comment puis-je mettre à jour le référentiel et chaque copie de travail pour qu'il y ait LF partout?
Chowlett
Avez-vous regardé ce guide Github?
Andy

Réponses:

237

Sans un peu d'informations sur les fichiers de votre référentiel (code source pur, images, exécutables, ...), il est un peu difficile de répondre à la question :)

À côté de cela, je considérerai que vous êtes prêt à utiliser par défaut LF comme fins de ligne dans votre répertoire de travail, car vous êtes prêt à vous assurer que les fichiers texte ont des fins de ligne LF dans votre référentiel .git que vous travailliez sous Windows ou Linux. . En effet, mieux vaut prévenir que guérir ....

Cependant, il existe une meilleure alternative: bénéficiez des fins de ligne LF dans votre répertoire de travail Linux, des fins de ligne CRLF dans votre répertoire de travail Windows ET des fins de ligne LF dans votre référentiel.

Comme vous travaillez partiellement sur Linux et Windows, assurez-vous que core.eolest défini sur nativeet core.autocrlfest défini sur true.

Ensuite, remplacez le contenu de votre .gitattributesfichier par le suivant

* text=auto

Cela permettra à Git de gérer la conversion automatique des fins de ligne pour vous, lors des validations et des extractions. Les fichiers binaires ne seront pas modifiés, les fichiers détectés comme étant des fichiers texte verront les fins de ligne converties à la volée.

Cependant, comme vous connaissez le contenu de votre référentiel, vous pouvez donner un coup de main à Git et l'aider à détecter les fichiers texte à partir de fichiers binaires.

Si vous travaillez sur un projet de traitement d'image basé sur C, remplacez le contenu de votre .gitattributesfichier par ce qui suit

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

Cela garantira que les fichiers dont l'extension est c, h ou txt seront stockés avec des fins de ligne LF dans votre dépôt et auront des fins de ligne natives dans le répertoire de travail. Les fichiers Jpeg ne seront pas touchés. Tous les autres bénéficieront du même filtrage automagique que ci-dessus.

Afin d'avoir une meilleure compréhension des détails internes de tout cela, je vous suggère de plonger dans ce très bon article "Attention à la fin de votre ligne" de Tim Clem, un Githubber.

En tant qu'exemple du monde réel, vous pouvez également jeter un œil à ce commit où ces modifications d'un .gitattributesfichier sont démontrées.

MISE À JOUR de la réponse en tenant compte du commentaire suivant

En fait, je ne veux pas de CRLF dans mes répertoires Windows, car mon environnement Linux est en fait une VirtualBox partageant le répertoire Windows

Logique. Merci pour la clarification. Dans ce contexte spécifique, le .gitattributesfichier à lui seul ne suffira pas.

Exécutez les commandes suivantes sur votre référentiel

$ git config core.eol lf
$ git config core.autocrlf input

Comme votre référentiel est partagé entre votre environnement Linux et Windows, cela mettra à jour le fichier de configuration local pour les deux environnements. core.eols'assurera que les fichiers texte portent des fins de ligne LF lors de l'extraction. core.autocrlfs'assurera que le CRLF potentiel dans les fichiers texte (résultant d'une opération de copier / coller par exemple) sera converti en LF dans votre référentiel.

En option, vous pouvez aider Git distinguer ce qui est un fichier texte en créant un .gitattributesfichier contenant quelque chose de semblable à ce qui suit:

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

Si vous avez décidé de créer un .gitattributesfichier, validez-le .

Enfin, assurez-vous de git statusmentionner "rien à valider (nettoyage du répertoire de travail)" , puis effectuez l'opération suivante

$ git checkout-index --force --all

Cela recréera vos fichiers dans votre répertoire de travail, en tenant compte de vos modifications de configuration et du .gitattributesfichier et en remplaçant tout CRLF potentiel négligé dans vos fichiers texte.

Une fois que cela est fait, chaque fichier texte de votre répertoire de travail portera des fins de ligne LF et git statusdevrait toujours considérer le répertoire de travail comme propre.

nulltoken
la source
34
En fait, je ne veux pas de CRLF dans mes répertoires Windows, car mon environnement Linux est en fait une VirtualBox partageant le répertoire Windows; et tandis que Notepad ++ etc. peut gérer LF uniquement sur Windows, il viest moins satisfait de CRLF. Est-ce que je veux juste le changer pour qu'il core.autocrlfsoit false(ou input)?
Chowlett
5
Excellente réponse. Une note rapide pour toute autre personne utilisant cette configuration: La ligne "* text = auto" doit être la première ligne de votre fichier .gitattributes afin que les lignes suivantes puissent remplacer ce paramètre.
Ari Patrick
9
@CMCDragonkai Selon votre shell, git checkout-index --force --allpeut fonctionner mieux. Le deuxième point semble un peu hors sujet par rapport à la question initiale. Que diriez-vous de poser une question dédiée?
nulltoken
8
Je ne comprends pas pourquoi .gitattributes ne peut pas gérer le cas du partage d'une copie de travail entre Linux et Windows. Ne pouvons-nous pas définir textet eol=lfobtenir le même résultat que celui décrit dans votre réponse via core.eolet core.autocrlf?
DanielSank
10
git checkout-index --force --allne fait rien pour moi. Ce qui fonctionne, c'est la liste des commandes dans les instructions GitHub pour traiter ce problème.
Roman Starkov
127

À partir de git 2.10 (publié le 03/09/2016), il n'est pas nécessaire d'énumérer chaque fichier texte séparément. Git 2.10 a corrigé le comportement de text = auto avec eol = lf . Source .

.gitattributes fichier à la racine de votre référentiel git:

* text=auto eol=lf

Ajoutez et validez.

Ensuite, vous pouvez suivre les étapes et tous les fichiers sont maintenant normalisés:

git rm --cached -r .  # Remove every file from git's index.
git reset --hard      # Rewrite git's index to pick up all the new line endings.

Source: Réponse de kenorb .

Koppor
la source
7
Git 2.10 a été publié le 3 Septembre 2016.
Stil
J'ai couru ceci et il a rassemblé tous mes fichiers non texte
Anthony
Vous pouvez définir explicitement le mode binaire sur certains fichiers. - Je me demande pourquoi la détection automatique est (toujours?!)
Cassée
Cela devrait être la réponse acceptée.
CletusW
25

Pour forcer les fins de ligne LF pour tous les fichiers texte, vous pouvez créer un .gitattributesfichier au niveau supérieur de votre référentiel avec les lignes suivantes (modifiez comme vous le souhaitez):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

qui garantit que tous les fichiers que Git considère comme des fichiers texte ont des LFfins de ligne normalisées ( ) dans le référentiel (normalement, la core.eolconfiguration contrôle celle que vous avez par défaut).

Sur la base des nouveaux paramètres d'attribut, tous les fichiers texte contenant des CRLF doivent être normalisés par Git. Si cela ne se produit pas automatiquement, vous pouvez actualiser un référentiel manuellement après avoir modifié les fins de ligne, de sorte que vous pouvez réexaminer et valider le répertoire de travail en suivant les étapes suivantes (compte tenu du répertoire de travail propre):

$ echo "* text=auto" >> .gitattributes
$ rm .git/index     # Remove the index to force Git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"

ou selon la documentation GitHub :

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git's index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

Voir aussi: @Charles Bailey post .

De plus, si vous souhaitez exclure des fichiers pour qu'ils ne soient pas traités comme du texte, désactivez leur attribut de texte, par exemple

manual.pdf      -text

Ou marquez-le explicitement comme binaire:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

Pour voir le fichier de normalisation git plus avancé, vérifiez .gitattributesau coeur de Drupal :

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

Voir également:

Kenorb
la source
2
1. text=autoest trompeur. Vous ne pouvez pas utiliser text=autoet eolensemble. Le paramètre eoldésactive la détection automatique des fichiers texte. C'est pourquoi vous devez spécifier tous ces types de fichiers. Si autoétait activé, vous n'auriez pas besoin de tout cela. 2. Vous n'avez pas besoin textet eol=lf. eol=lfdéfinit efficacement text.
Ben
2
2ème ce que @Ben a dit, cette configuration est actuellement erronée et dangereuse si vous ne marquez pas explicitement tous les fichiers binaires.
Michael R
1
J'ai lu que * text=auto eol=lfle premier text=autoest remplacé par eol=lf. Où avez-vous trouvé cette fonctionnalité? Voici ma source: stackoverflow.com/questions/29435156/…
CMCDragonkai
Supprimé * text=auto eol=lfde l'exemple, car il a également été supprimé de Drupal. Pensez également à supprimer les commentaires.
kenorb
4
Il est important de noter que ce que @Ben a dit n'est plus vrai et que c'était toujours un bogue - pas un comportement intentionnel.
Semmel