Kann git-merge Unterschiede am Zeilenende ignorieren?


150

Ist es möglich git merge, Unterschiede am Zeilenende zu ignorieren?

Vielleicht stelle ich die falsche Frage ... aber:

Ich habe versucht , uisng config.crlf inputaber die Dinge bekamen ein bisschen chaotisch und außer Kontrolle geraten , besonders wenn ich wandte sie nach der Tat .

Zum einen scheint das Anwenden dieser Konfiguration nachträglich keine Auswirkungen auf Dateien zu haben, die vor dem Anwenden dieser Option in das Repository übernommen wurden. Eine andere Sache ist, dass plötzlich alle Commits zu vielen nervigen Warnmeldungen über die Konvertierung von CRLF in LF führen.

Um ehrlich zu sein, ist es mir egal, welches Zeilenende verwendet wird, ich persönlich bevorzuge den Unix-Stil \n, aber was auch immer. Alles, was mich interessiert, ist git merge, ein bisschen schlauer zu sein und die Unterschiede in den Zeilenenden zu ignorieren.

Manchmal habe ich zwei identische Dateien, aber git markiert sie als Konflikt (und der Konflikt ist die gesamte Datei), einfach weil sie ein anderes Zeilenendezeichen verwenden.

Aktualisieren:

Ich habe herausgefunden, dass git diffeine --ignore-space-at-eolOption akzeptiert wird. Wäre es möglich, git mergediese Option auch verwenden zu lassen?


28
Oh ich wünschte. Diese Zeilenende-Sache in Git ist total kaputt
1800 INFORMATION

Gerade ein Testfall hinzugefügt, der diese Zusammenführungstools von Drittanbietern veranschaulicht, ignoriert den EOL-Stil während einer Zusammenführung
VonC

Um zu verdeutlichen (soweit ich das beurteilen kann): Es gibt keine Möglichkeit, Git dazu zu bringen, CRs zu ignorieren, sondern sich über alle anderen nachgestellten Leerzeichen zu beschweren.
Stephen

Schauen Sie sich git config merge.renormalize true
unbedingt

Antworten:


115

Update 2013:

Neuere git Versionen mit merge mit Strategie autorisieren recursiveund Strategie - Option ( -X):

git merge -s rekursiv -Xignore-space-at-eol

Die Verwendung von " -Xignore-space-change" ist aber auch möglich

  • Fab-V erwähnt unten :
    Git Merge Master -s rekursiv -X renormieren
    
    

jakub.g auch kommentiert , dass die Strategien arbeiten auch mit Rosinenpickerei :

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

Das funktioniert viel besser als ignore-all-space.


Ursprüngliche Antwort (Mai 2009)

Der Patch zum Ignorieren des EOL-Stils wurde im Juni 2007 vorgeschlagen , betrifft jedoch nur git diff --ignore-space-at-eol, nicht git merge.

Zu diesem Zeitpunkt wurde die Frage gestellt:

Sollte --ignore-space-at-eoleine Option sein git-merge?
Bei Zusammenführungen kommt es auf diese Funktionalität an.
Was ist die Semantik einer automatisch aufgelösten Zusammenführung mit diesen Optionen? Werden sie nur zur Erkennung von Umbenennungen verwendet oder kennzeichnen wir z. B. Konflikte nicht nur mit Leerzeichenänderungen? Und wenn nicht, welche Version akzeptieren wir automatisch?

Julio C Hamano war nicht gerade begeistert:

Das ist sicherlich verlockend, aber ich vermute, dass dies späteren Runden überlassen werden sollte.
Ich vermute, dass es ein Konzept von zwei verschiedenen Arten von Unterschieden einführen würde, von denen eine mechanisch verarbeitet werden soll (dh die Verwendung beim Zusammenführen mit "git-merge-recursive" und die Anwendung bei "git-am") und die andere von inspiziert werden soll Menschen zu verstehen.
Es kann oft nützlich sein, die Eingabe für den letzteren Fall zu mischen, obwohl die Ausgabe aus dem Vergleich von munged Eingabedateien für mechanische Anwendungen möglicherweise nicht ohne weiteres verwendet werden kann.

Die allgemeine Idee git mergebesteht darin, sich auf das Merge-Tool eines Drittanbieters zu verlassen.

Zum Beispiel habe ich DiffMerge als Tool für Git-Merge eingerichtet und einen Regelsatz festgelegt, mit dem dieses Merge-Tool eol für bestimmte Dateitypen ignorieren kann.


Setup unter Windows mit MSysGit1.6.3, entweder für DOS- oder Git-Bash-Sitzungen, mit DiffMerge oder KDiff3:

  • Legen Sie ein Verzeichnis in Ihrem PATH fest (hier :) c:\HOMEWARE\cmd.
  • Fügen Sie in diesem Verzeichnis das Skript merge.sh hinzu (Wrapper für Ihr bevorzugtes Merge-Tool).

merge.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Deklarieren Sie Ihren Merge-Wrapper für Git

Git-Konfigurationsbefehle:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • Überprüfen Sie, ob autoCRLF falsch ist

Git-Konfiguration auf Systemebene:

git config ---system core.autoCRLF=false
  • Testen Sie, ob DiffMerge oder KDiff3 diese Zeilen während einer Zusammenführung ignorieren, wenn zwei Zeilen identisch sind (aber ihre Äol-Zeichen).

DOS-Skript (Hinweis: Der Befehl dos2unix stammt von hier und wird zur Simulation eines Unix-EOL-Stils verwendet. Dieser Befehl wurde in das am Anfang dieser Antwort angegebene Verzeichnis kopiert.):

C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_merge>git mergetool Merging the files: a.txt Normal merge conflict for 'a.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):

An diesem Punkt (durch Drücken von "Return") wird DiffMerge oder KDiff3 geöffnet, und Sie werden selbst sehen, welche Zeilen tatsächlich zusammengeführt und welche Zeilen ignoriert werden.

Warnung : Die Ergebnisdatei befindet sich mit DiffMerge immer im Windows-EOL-Modus (CRLF).
KDiff3 bietet das Speichern auf die eine oder andere Weise an.


Danke für den Tipp! Meld und FileMerge in Mac scheinen ebenfalls großartige Apps zu sein.
Léo Léopold Hertz 25

1
Zur Information, die Strategien funktionieren auch mit Kirschernte : git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize (das funktioniert viel besser als ignore-all-space)
jakub.g

1
@ jakub.g guter Punkt! Ich habe es in die Antwort für mehr Sichtbarkeit aufgenommen.
VonC

98

Ich suchte nach der gleichen Antwort und fand dies heraus

Zusammenführen von Zweigen mit unterschiedlichen Checkin / Checkout-Attributen

Wenn Sie einer Datei Attribute hinzugefügt haben, die dazu führen, dass sich das kanonische Repository-Format für diese Datei ändert, z. B. das Hinzufügen eines Clean / Smudge-Filters oder von Text / Eol / Ident-Attributen, führt das Zusammenführen von Elementen, bei denen das Attribut nicht vorhanden ist, normalerweise zu Zusammenführungskonflikten .

Um diese unnötigen Zusammenführungskonflikte zu vermeiden, kann git angewiesen werden, beim Auflösen einer Drei-Wege-Zusammenführung ein virtuelles Aus- und Einchecken aller drei Phasen einer Datei durchzuführen, indem die Konfigurationsvariable merge.renormalize festgelegt wird. Dadurch wird verhindert, dass durch die Check-in-Konvertierung verursachte Änderungen zu falschen Zusammenführungskonflikten führen, wenn eine konvertierte Datei mit einer nicht konvertierten Datei zusammengeführt wird.

Solange ein "Verwischen → Bereinigen" auch bei bereits verwischten Dateien zu derselben Ausgabe wie ein "Bereinigen" führt, löst diese Strategie automatisch alle filterbezogenen Konflikte. Filter, die nicht auf diese Weise funktionieren, können zusätzliche Zusammenführungskonflikte verursachen, die manuell gelöst werden müssen.

Das Ausführen dieses Befehls in einem beliebigen Repository reicht also aus:

git config merge.renormalize true

20
Dies verdient nun die Standardantwort. Vieles hat sich geändert, seit die Frage zum ersten Mal gestellt wurde. Wie Sie sagen, ist die Handhabung von git jetzt in merge.renormalize integriert.
Anton I. Sipos

Das ist einfach fantastisch .. rettet meinen Tag
Matthaeus



4

Was ich getan habe, war, alles als Standard zu belassen (dh autocrlf = true), alle Dateien zu berühren (find. -Exec touch {} \;), git sie als 'modifiziert' ansehen zu lassen und sie zurückzuschreiben und damit fertig zu sein. Andernfalls werden Sie entweder immer von nervigen Nachrichten oder überraschenden Unterschieden geplagt oder müssen alle Whitespace-Funktionen von git deaktivieren.

Sie verlieren Schuldinformationen, aber es ist besser, dies eher früher als später zu tun :)


4

"git merge -Xrenormalize" funktioniert wie ein Zauber.




0

Es scheint mir jetzt, dass der beste Weg darin besteht, die Zeilenenden in beiden Zweigen zu normalisieren (und festzuschreiben), bevor sie zusammengeführt werden.

Ich googelte "crlf in lf konvertieren" und fand dies als erstes Ergebnis:
http://stahlforce.com/dev/index.php?tool=remcrlf

Ich habe es heruntergeladen und verwendet, scheint ein schönes Werkzeug zu sein.

>sfk remcr . .py

Stellen Sie jedoch sicher, dass Sie ein Verzeichnis und einen Dateityp (z. B. .py) angeben, da sonst versucht wird, den Inhalt des .gitVerzeichnisses zu verfälschen !


0

AFAICT (ich habe es nicht ausprobiert) Sie können git diffden Zweig, den Sie zusammenführen möchten, mit dem gemeinsamen Vorfahren vergleichen und dann die Ergebnisse mit anwenden git apply. Beide Befehle --ignore-whitespacebieten Optionen zum Ignorieren von Zeilenenden und Leerzeichenfehlern.

Wenn der Patch nicht sauber angewendet wird, wird der gesamte Vorgang leider abgebrochen. Sie können Zusammenführungskonflikte nicht beheben. Es gibt eine --rejectOption, nicht stapelbare Hunks in .rejDateien zu belassen. Dies ist hilfreich , entspricht jedoch nicht den in einer Datei angezeigten Zusammenführungskonflikten.


-1

Nach dem Lesen Zusammenführen von Zusammenführungskonflikten: Erzwingen Sie das Überschreiben aller Dateien

Ich habe endlich meine Version dieses Problems behoben. Ich habe versucht, Updates aus dem Upstream-Repo abzurufen, aber mein aktuelles Repo hatte CRLF-Probleme und konnte als Ergebnis nicht zusammengeführt werden. Es sollte beachtet werden, dass ich KEINE LOKALEN ÄNDERUNGEN hatte, über die ich mir Sorgen machen musste. Die folgenden Schritte haben mein Problem behoben:

Gemäß den Anweisungen von github zum Synchronisieren von Gabeln ( https://help.github.com/articles/syncing-a-fork/ ):

  1. git fetch upstream

  2. git reset --hard upstream/master
    Mein begrenztes Verständnis von Git sagt mir, dass dies das tut, was ich will - meine Gabel neu zu gründen (ohne tatsächlich nicht festgeschriebene Änderungen), um alle Änderungen zu erhalten, die an der Upstream-Quelle vorgenommen wurden. Laut der Quellseite sollte dieser Schritt normalerweise nicht erforderlich sein, aber das CRLF-Problem machte ihn erforderlich.

  3. git merge upstream/master

  4. git push

1
Sie erkennen, dass git reset --hard upstream/masterIhre lokale Niederlassung weggeworfen und darauf hingewiesen wird upstream/master, was git merge upstream/masterein No-Op macht?
Christoffer Hammarström

-1

Ich empfehle jedoch, ein Tool wie sed zu verwenden, um korrekte Zeilenenden zu erzielen, und dann Dateien zu diff. Ich verbrachte paar Stunden auf die Differenzen zwischen Projekten mit verschiedenen Zeilenenden.

Der beste Weg war:

  1. Kopieren Sie nur Projektdateien ( .gitVerzeichnis weglassen ) in ein anderes Verzeichnis, erstellen Sie ein Repository darin, fügen Sie dann Dateien hinzu und schreiben Sie sie fest (sollte sich im Hauptzweig des neuen Repositorys befinden).
  2. Kopieren Sie Dateien aus dem zweiten Projekt in denselben Ordner, aber in einen anderen Zweig, z. B. dev( git checkout -b dev), schreiben Sie Dateien in diesen Zweig und führen Sie sie aus (wenn sich das erste Projekt im Master befindet) git diff master..dev --names-only , um nur die Namen der geänderten Dateien anzuzeigen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.