État Git ignore les fins de ligne / fichiers identiques / environnement Windows et Linux / dropbox / mled

113

Comment faire

état git

ignorer les différences de fin de ligne?

Informations de fond:

J'utilise au hasard Windows et Linux pour travailler sur le projet. Le projet est dans Dropbox.

J'ai trouvé beaucoup de choses sur la façon dont git diff ignore les fins de ligne. Depuis que j'utilise meld git diff ouvre meld pour chaque fichier. Et meld dit "fichier identique".

Alors, comment éviter cela. Git ne devrait ouvrir la fusion que pour les fichiers modifiés. Et git status ne devrait pas signaler les fichiers comme modifiés si seule la fin du fichier est différente.

EDIT: Cause:

Cela s'est produit à cause de ce paramètre sur Windows

core.autocrlf true

J'ai donc vérifié la copie de travail sous Linux et défini core.autocrlf sur false sous Windows.

Ce serait toujours bien de savoir comment faire ignorer les différentes nouvelles lignes de git status.

Thorsten Niehues
la source
3
Si vous partagez le fichier en utilisant Dropbox sur différentes plates-formes, cela se produira à moins que vous ne disiez explicitement à git de traiter tous les fichiers comme binaires. La bonne solution est de ne pas utiliser dropbox pour les dépôts git
Petesh
remarquez : stackoverflow.com/questions/2825428/… - cela peut aider un peu
Petesh
J'ai découvert comment cela fonctionne bien avec Dropbox: en définissant core.autocrlf sur false
Thorsten Niehues
3
AFAIK dire à git de traiter les fichiers comme des binaires a également pour effet secondaire de changer la façon dont il diffère le fichier. La bonne solution est de dire à git d'ignorer les fins de ligne. 2 de mes choses les moins préférées: gérer les problèmes de fin de ligne et FUD sournois inutile sur la façon dont les gens mettent en place leurs
dépôts
Wow, il m'a fallu un certain temps pour que ce problème core.autocrlfsoit la cause première sous Windows, mais aussi un remède sous Linux. Le problème est qu'il autocrlfest global sous Windows et que le dépôt n'a pas ce paramètre .git/config. En exécutant un local, git config core.autocrlf trueje me suis débarrassé des modifications fausses sur ma copie de travail NTFS clonée sous Windows mais accessible sous Linux. (maintenant il n'y a que des changements fallacieux avec des liens symboliques - les liens symboliques NTFS FONCTIONNENT sur les montages fuseblk, mais Git les voit comme modifiés ...)
Tomasz Gandor

Réponses:

104

Essayez de définir la valeur core.autocrlf comme ceci:

git config --global core.autocrlf true
Saša Šijak
la source
7
@ThorstenNiehues J'utilise ce paramètre sur certains projets de travail. Au travail, je dois utiliser Windows, chez moi, j'utilise Mac et Linux. Avant cela, j'avais le même problème que vous, après ce réglage, tout allait bien.
Saša Šijak
1
C'est étrange car une extraction sous Windows a \ r \ n des fins de ligne sous Linux uniquement \ n Avez-vous les deux copies de travail dans Dropbox (ou similaire)?
Thorsten Niehues
1
@ThorstenNiehues Non, le dépôt git est sur github. Hmm, peut-être que Dropbox est en quelque sorte en train de visser les fins de ligne quand il synchronise les fichiers? Il semble étrange d'utiliser dropbox pour git. Essayez d'utiliser bitbucket (il a des référentiels privés gratuits), créez simplement un petit dépôt et testez vos 2 machines avec de petits fichiers texte.
Saša Šijak
1
1. La copie de travail et le dépôt local sont dans Dropbox (je n'ai pas besoin d'un référentiel public) c'est probablement la différence
Thorsten Niehues
3
Sous Windows: core.autocrlf trueest un paramètre de travail dans CygWin. core.safecrlf falseest un paramètre de travail dans git bash ou mingw
DrumM
43

Utilisez plutôt .gitattributes, avec le paramètre suivant:

# Ignore all differences in line endings
*        -crlf

.gitattributes se trouverait dans le même répertoire que votre .gitconfig global. Si .gitattributes n'existe pas, ajoutez-le à ce répertoire. Après avoir ajouté / modifié .gitattributes, vous devrez effectuer une réinitialisation matérielle du référentiel afin d'appliquer avec succès les modifications aux fichiers existants.

Éboueur
la source
Cela a fonctionné pour moi dans un flux, mais lorsque j'ai essayé de le créer dans un autre flux pour le même projet, cela montre toujours les différences de Newline.
pfernandom
1
@pfernandom, avez-vous peut-être plusieurs .gitattributes dans votre projet? Il examinera d'abord la version la plus "locale", donc si vous en avez une dans le répertoire local où se trouvent les fichiers, il utilisera celle-là sur l'ensemble de votre projet.
Trashman
Doit-il avoir 8 espaces avant -crlf?
Igonato du
Cela ne devrait pas avoir d'importance
Trashman
Cela fait plus que simplement ignorer les fins de ligne pour git status. Cela change en fait la façon dont les fichiers sont archivés dans le référentiel. ref: git-scm.com/docs/gitattributes#_code_text_code
Vince
31

Cette réponse semble pertinente puisque l'OP fait référence à un besoin de solution multi-OS. Cet article d'aide Github détaille les approches disponibles pour gérer les fins de lignes entre les systèmes d'exploitation. Il existe des approches globales et per-repo pour gérer les fins de ligne cross-os.

Approche globale

Configurez la gestion des fins de ligne Git sous Linux ou OS X:

git config --global core.autocrlf input

Configurez la gestion des fins de ligne Git sous Windows:

git config --global core.autocrlf true

Approche par pension:

À la racine de votre .gitattributesdépôt , créez un fichier et définissez les paramètres de fin de ligne pour vos fichiers de projet, une ligne à la fois au format suivant: path_regex line-ending-settingsline-ending-settingsest l'un des éléments suivants:

  • texte
  • binaire (fichiers pour lesquels Git ne doit pas modifier les fins de ligne - car cela peut empêcher certains types d'images tels que les PNG de ne pas s'afficher dans un navigateur)

La textvaleur peut être configurée davantage pour indiquer à Git comment gérer les fins de ligne pour les fichiers correspondants:

  • text - Modifie les fins de ligne en terminaisons de ligne natives du système d'exploitation.
  • text eol=crlf- Convertit les fins de ligne à la CRLFcaisse.
  • text eol=lf- Convertit les fins de ligne à la LFcaisse.
  • text=auto - Par défaut sensible qui laisse la gestion de la ligne à la discrétion de Git.

Voici le contenu d'un exemple de fichier .gitattributes:

# Set the default behavior for all files.
* text=auto

# Normalized and converts to 
# native line endings on checkout.
*.c text
*.h text

# Convert to CRLF line endings on checkout.
*.sln text eol=crlf

# Convert to LF line endings on checkout.
*.sh text eol=lf

# Binary files.
*.png binary
*.jpg binary

Plus d'informations sur la façon d'actualiser votre dépôt après avoir modifié les paramètres de fin de ligne ici . Tldr:

sauvegardez vos fichiers avec Git, supprimez tous les fichiers de votre référentiel (à l'exception du répertoire .git), puis restaurez tous les fichiers en même temps. Enregistrez vos fichiers actuels dans Git, afin qu'aucun de votre travail ne soit perdu.

git add . -u

git commit -m "Saving files before refreshing line endings"

Supprimez l'index et forcez Git à réanalyser le répertoire de travail.

rm .git/index

Réécrivez l'index Git pour récupérer toutes les nouvelles fins de ligne.

git reset

Afficher les fichiers normalisés réécrits.

Dans certains cas, c'est tout ce qui doit être fait. D'autres devront peut-être effectuer les étapes supplémentaires suivantes:

git status

Ajoutez à nouveau tous vos fichiers modifiés et préparez-les pour une validation. C'est votre chance d'inspecter quels fichiers, le cas échéant, n'ont pas été modifiés.

git add -u

Il est parfaitement sûr de voir ici un grand nombre de messages indiquant "avertissement: CRLF sera remplacé par LF dans le fichier."

Réécrivez le fichier .gitattributes.

git add .gitattributes

Validez les modifications dans votre référentiel.

git commit -m "Normalize all the line endings"

user4603841
la source
18

Problème lié aux commandes git sur le système d'exploitation Windows:

$ git add --all

Attention: LF sera remplacé par CRLF dans ...

Le fichier aura ses fins de ligne d'origine dans votre répertoire de travail.

Résolution :

$ git config --global core.autocrlf false     
$ git add --all 

Aucun message d'avertissement n'apparaît.

winstonhong
la source
vous devez le faire dans tous les systèmes d'exploitation que vous utilisez, c'est-à-dire sous Windows et sous Linux. Rember chaque OS a son propre fichier global .git / config, vous devez donc rendre ces paramètres similaires. C'est pourquoi @Thorsten vous aviez des problèmes. Mais j'ai défini l'indicateur sur vrai au lieu de faux.
Emmanuel Mahuni
Cette solution fonctionne également sous Linux (la réponse @ SašaŠijak ne fonctionne pas pour moi)
juliocesar
4

J'ai créé un script pour ignorer les différences de fin de ligne:

Il affichera les fichiers qui ne sont pas ajoutés à la liste de validation et qui ont été modifiés (après avoir ignoré les différences dans les fins de ligne). Vous pouvez ajouter l'argument "add" pour ajouter ces fichiers à votre commit.

#!/usr/bin/perl

# Usage: ./gitdiff.pl [add]
#    add : add modified files to git

use warnings;
use strict;

my ($auto_add) = @ARGV;
if(!defined $auto_add) {
    $auto_add = "";
}

my @mods = `git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-`;
chomp(@mods);
for my $mod (@mods) {
    my $diff = `git diff -b $mod 2>/dev/null`;
    if($diff) {
        print $mod."\n";
        if($auto_add eq "add") {
            `git add $mod 2>/dev/null`;
        }
    }
}

Code source: https://github.com/lepe/scripts/blob/master/gitdiff.pl

Mises à jour :

  • correction par evandro777: Lorsque le fichier a de l'espace dans le nom de fichier ou le répertoire
lépe
la source
Merci! C'est la seule façon pour moi d'obtenir la vraie différence. Il y a juste un problème qui s'est produit avec 3 lignes imprimées, montrant cette erreur: sh: 1: Erreur de syntaxe: Chaîne entre guillemets non
terminée
1
Un correctif pour un problème de script: Le problème: lorsque le fichier a de l'espace dans le nom de fichier ou le répertoire, git utilisera "", donc le script se brise. Le correctif est de changer cette ligne: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | awk '{ print \$2 }'; à ceci: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-;
evandro777
@ evandro777: Merci! J'ai mis à jour à la fois la réponse et le code git.
lepe
3

J'utilise à la fois Windows et Linux, mais la solution core.autocrlf truene m'a pas aidé. Je n'ai même rien changé après git checkout <filename>.

J'utilise donc une solution de contournement pour remplacer git status-gitstatus.sh

#!/bin/bash

git status | grep modified | cut -d' ' -f 4 | while read x; do
 x1="$(git show HEAD:$x | md5sum | cut -d' ' -f 1 )"
 x2="$(cat $x | md5sum | cut -d' ' -f 1 )"

 if [ "$x1" != "$x2" ]; then
    echo "$x NOT IDENTICAL"
 fi
done

Je viens de comparer md5sumun fichier et son frère au référentiel.

Exemple de sortie:

$ ./gitstatus.sh
application/script.php NOT IDENTICAL
application/storage/logs/laravel.log NOT IDENTICAL
shukshin.ivan
la source
2
peut-être que vous pouvez utiliser "git diff -b" pour chaque fichier pour vérifier les changements excel les changements d'espaces blancs
Ivan