Désactiver les conversions Git EOL

100

J'essaie de faire en sorte que git ne modifie aucune fin de ligne pour aucune opération. Malheureusement, il semble que ce soit le cas, peu importe quoi. Je l'ai réduit au cas de test suivant, qui a autant de mécanismes différents pour désactiver ce comportement que je pouvais trouver.


  • Commencez par deux machines (ordinateur Windows = A, ordinateur Linux = B)
  • Sur les deux machines: git config --global core.autocrlf false
  • Sur les deux machines: git config --global core.eol crlf(juste au cas où)

  • Créez un nouveau référentiel sur A. À partir d'un dossier vide:
    • git init --shared(puis affichez le .gitrépertoire créé )
    • Créer un nouveau fichier .gitignoredans le référentiel
    • Créez un nouveau fichier .gitattributesdans le référentiel avec une seule ligne:* -text
    • git add ., puis git commit -m "initial commit"pour contourner, par exemple ceci .
    • git branch master_recv
    • Ajouter des télécommandes
  • Créer un nouveau fichier document.txtdans le référentiel contenant CRLF
  • Commit:, git add -Aalorsgit commit -m "<something>"
  • Notez que A document.txtcontient toujours CRLF (et le supprimer et réinitialiser avec --hardrenvoie la version toujours avec CRLF)

  • SCP tout le répertoire sur l'ordinateur B
  • Ajouter un nouveau fichier new filecontenant CRLF
  • Commit:, git add -Aalorsgit commit -m "<something>"
  • Notez que les B document.txtet les B new filecontiennent toujours CRLF

  • Tirez le maître de B vers A: git pull <remote> master:master_recv
  • A document.txtest devenu LF. Le fichier ajouté new filecontient également LF.

Le problème ne se produit pas si B est une machine Windows.

Imallett
la source
A core.autocrlf toujours été faux? On dirait que vous avez déjà des \nfins de ligne dans votre référentiel? Il n'y a aucun paramètre à modifier \ndans votre référentiel \r\ndans votre répertoire de travail.
Edward Thomson
Il n'a pas toujours été défini (par exemple lorsque le dépôt a été créé à l'origine). Cependant, il ne devrait pas y avoir de fin de ligne CR dans le dépôt déjà. De plus, encore une fois, je ne veux aucun changement.
imallett
Je demande parce que votre configuration doit conserver vos fins de ligne en tant que CRLF. Pourriez-vous publier un fichier dans votre référentiel avec son ID d'objet juste pour mon édification (certes probablement ennuyeuse)?
Edward Thomson
@EdwardThomson que voulez-vous dire? Le dépôt n'est pas public (puisque la machine Linux ne l'est pas). Je suppose que vous voulez un fichier d'exemple. Voir modifier.
imallett
Oui, je suis d'accord que ce fichier a des fins de ligne CRLF. Pouvez-vous clarifier une chose: vous avez mentionné que "les retours à la ligne de la machine Windows deviennent CR!" C'était sûrement une faute de frappe, ou obtenez-vous vraiment des fins de ligne de retour chariot de type Mac OS 9?
Edward Thomson

Réponses:

74

À l'intérieur de votre projet, il devrait y avoir un .gitattributesfichier. La plupart du temps, cela devrait ressembler à ci-dessous (ou à cette capture d'écran ):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

Passez * text=autoà * text=falsepour désactiver la gestion automatique (voir la capture d'écran ).

Comme ça:

entrez la description de l'image ici

Si votre projet n'a pas de fichier .gitattributes, les fins de ligne sont définies par vos configurations git. Pour modifier vos configurations git, procédez comme suit:

Accédez au fichier de configuration dans ce répertoire:

1) C: \ ProgramData \ Git \ config

2) Ouvrez le fichier de configuration dans Notepad ++ (ou n'importe quel éditeur de texte que vous préférez)

3) Remplacez "autocrlf =" par false.

entrez la description de l'image ici

Gène
la source
31
Pourquoi utiliser des images au lieu de balises de code? Très peu pratique
Clint
31
Parce que je peux ajouter une grande boîte rouge dans l'image pour mettre en évidence des choses.
Gene
21
L'utilisation * text=falsen'annule pas le texte: elle laisse le texte défini sur la valeur de chaîne false. Cela a le même effet que de laisser le texte non spécifié (pas spécifiquement non défini). Utiliser * -textlui donne le paramètre spécial non défini. La désactivation de l'attribut text sur un chemin indique à git de ne pas tenter de conversion de fin de ligne lors de l'enregistrement ou du retrait.
JustAMartin
Merci @Gene pour cette réponse. Cela m'a rendu fou toute la journée, et celui-ci l'a résolu pour moi!
LeopardSkinPillBoxHat
7
Désolé de dire que je ne peux pas dire merci pour cette réponse. Cela m'a coûté une demi-journée pour découvrir que quelqu'un avait suivi les conseils trompeurs. Comme l'a souligné @JustAMartin, cela * text=falsen'a pas d'effet. Veuillez corriger la réponse!
Paul B.
47

Une solution simple est:

  • assurez-vous que core.autocrlf est défini sur false pour tous les dépôts:
    git config --global core.autocrlf false
  • re-clonez votre dépôt et vérifiez qu'aucune conversion EOL n'est effectuée.
  • ou, depuis Git 2.16 (Q1 2018) , conservez votre dépôt actuel et effectuez ungit add --renormalize .

S'il y a des conversions effectuées automatiquement, cela signifie qu'une .gitattributes core.eoldirective est présente dans le dépôt.

Avec Git 2.8+ (mars 2016) , vérifiez s'il y a encore une transformation eol avec:

git ls-files --eol
VonC
la source
2
NE PAS UTILISER autocrlfAUJOURD'HUI! unsetted autocrlféquivaut à false. Vous êtes à la traîne des mouvements à la mode dans Git
Lazy Badger
1
Comme ci-dessus, j'avais essayé cela (mais pas avec le drapeau global), et cela n'a pas fonctionné. la version git est 1.8.5.2.
imallett
@IanMallett "À ce stade, il semble que la machine Linux a toujours CRLF": il le fera jusqu'à ce que vous re-normalisiez son contenu, ou le cloniez (comme vous l'avez fait sous Windows)
VonC
11

Je l'ai compris. Il semble que le programme SCP convertissait les fins de ligne. J'ai remarqué cela lorsque j'ai essayé de créer délibérément un fichier avec des fins LF, puis en observant qu'il apparaissait en tant que CRLF lors du téléchargement.

Puisque c'était la solution pour moi, j'accepte cette réponse, mais les gens du futur devraient également se référer aux autres réponses pour une solution plus générale.

Imallett
la source
1
Bonne prise, plus précise que ma réponse. +1
VonC
4

De la page de manuel gitattributes (5) Sujet "Effets"

text

Cet attribut active et contrôle la normalisation de fin de ligne. Lorsqu'un fichier texte est normalisé, ses fins de ligne sont converties en LF dans le référentiel. Pour contrôler le style de fin de ligne utilisé dans le répertoire de travail, utilisez l' eolattribut pour un seul fichier et la core.eol variable de configuration pour tous les fichiers texte.

Set

La définition de l'attribut de texte sur un chemin permet la normalisation de fin de ligne et marque le chemin comme un fichier texte. La conversion de fin de ligne s'effectue sans deviner le type de contenu.

Unset La désactivation de l'attribut text sur un chemin indique à Git de ne pas tenter de conversion de fin de ligne lors de l'archivage ou du retrait.

core.autocrlfdans le nouveau (1.7.2+) Git non utilisé, core.eolet réglage correct | désactivation de l'attribut texte considéré comme un moyen plus fiable

Blaireau paresseux
la source
Dans le .gitattributesfichier, j'avais cependant tout désactivé explicitement sous forme de texte, non? De plus, je ne le vois pas avec une option pour qu'il ne fasse pas de conversion (bien que cela crlfpuisse n'avoir aucun effet)?
imallett
6
Chose importante qui devient souvent confuse - pour annuler textet empêcher toute conversion, vous devez définir .gitattributes sur * -text et non sur * text=false. falsen'est pas une valeur valide pour l' textattribut - git ne le reconnaîtra pas et reviendra à son paramètre autocrlf par défaut à la place. De plus, après avoir modifié la textvaleur, vous devez sauvegarder tous les fichiers de votre dépôt local, effectuer une validation, puis restaurer les fichiers avec la fin de ligne correcte selon vos besoins, et les valider à nouveau. Ensuite, votre fin de ligne ne sera plus jamais modifiée par git.
JustAMartin