Ist es möglich für git merge
Unterschiede am Zeilenende ignorieren?
Vielleicht stelle ich die falsche Frage … aber:
Ich habe es versucht config.crlf input
aber die Dinge wurden ein bisschen chaotisch und außer Kontrolle geraten, besonders als ich es anwendete nach dem Fakt.
Zum einen scheint das nachträgliche Anwenden dieser Konfiguration keine Auswirkungen auf Dateien zu haben, die vor dem Anwenden dieser Option in das Repository übertragen wurden. Eine andere Sache ist, dass jetzt plötzlich alle Commits zu vielen nervigen Warnmeldungen führen, dass CRLF in LF konvertiert wird.
Um ehrlich zu sein, ist es mir egal, welches Zeilenende verwendet wird, ich persönlich bevorzuge den Unix-Stil \n
, aber egal. Alles, was mich interessiert, ist für git merge
ein bisschen schlauer zu sein und die Unterschiede in den Zeilenenden zu ignorieren.
Manchmal habe ich zwei identische Dateien, aber git würde sie als in Konflikt stehend markieren (und der Konflikt ist die ganz Datei), einfach weil sie ein anderes Zeilenendezeichen verwenden.
Aktualisieren:
Ich habe herausgefunden, dass git diff
akzeptiert a --ignore-space-at-eol
Option, wäre es möglich zu vermieten git merge
auch diese Möglichkeit nutzen?
Aktualisierung 2013:
Neuere Git-Versionen erlauben die Verwendung von Merge with Strategy recursive
und Strategie Möglichkeit (-X
):
Aber mit “-Xignore-space-change
“ ist auch eine Möglichkeit
jakub.g kommentiert auch, dass die Strategien funktionieren auch mit Cherry-Picking:
git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize
Das funktioniert viel besser als ignore-all-space
.
Vor Git 2.29 (4. Quartal 2020) sollten alle „Mergy“-Vorgänge, die intern die Merge-rekursive Maschinerie verwenden, die merge.renormalize
Konfiguration, aber viele von ihnen taten es nicht.
Sehen begehen 00906d6, Übertrage 8d55225, Commit 6f6e7cf, fe48efb begehen (03.08.2020) von Elijah Newren (newren
).
(Zusammengeführt von Junio C. Hamano — gitster
— in Commit 433925910.08.2020)
merge
: machen merge.renormalize
Arbeit für alle Anwendungen von Merge-Maschinen
Unterzeichnet von: Elijah Newren
Die ‘merge
‘ Befehl ist nicht der einzige, der Zusammenführungen durchführt; andere Befehle wie checkout -m
oder rebase auch tun.
Leider ist der einzige Bereich des Codes, der nach “merge.renormalize
” Konfigurationseinstellung war drin builtin/merge.c
was bedeutet, dass es nur Zusammenführungen betreffen könnte, die vom “merge
” Befehl.
Verschieben Sie die Handhabung dieser Konfigurationseinstellung nach merge_recursive_config()
damit auch andere Befehle davon profitieren können.
Ursprüngliche Antwort (Mai 2009)
Der Patch zum Ignorieren des EOL-Stils wurde in vorgeschlagen Juni 2007aber es betrifft nur git diff --ignore-space-at-eol
nicht git merge
.
Damals wurde die Frage gestellt:
Sollte --ignore-space-at-eol
eine 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 in Kraft — werden sie nur für die Erkennung von Umbenennungen verwendet, oder markieren wir zB keine Konflikte mit nur Whitespace-Änderungen? Und wenn nicht, welche Version akzeptieren wir automatisch?
Julio C Hamano war nicht gerade begeistert:
Das ist sicherlich verlockend, aber ich vermute, das sollte späteren Runden vorbehalten bleiben.
Ich vermute, dass es ein Konzept von zwei verschiedenen Arten von Diffs einführen würde, von denen eines mechanisch verarbeitet werden soll (dh in Merge mit “git-merge-recursive” verwendet und mit “git-am” angewendet wird) und ein anderes von überprüft werden soll Menschen zu verstehen.
Es kann oft nützlich sein, die Eingabe für den letzteren Fall zu mungieren, auch wenn die Ausgabe aus dem Vergleich von mungierten Eingabedateien möglicherweise nicht ohne weiteres für eine mechanische Anwendung verwendbar ist.
Die allgemeine Idee, wenn es darum geht git merge
ist auf das Zusammenführungstool des Drittanbieters angewiesen.
Zum Beispiel habe ich eingerichtet DiffMerge um das Tool für Git Merge zu sein, Einstellung a Regelsatz die es diesem Zusammenführungstool ermöglichen, eol für bestimmte Dateitypen zu ignorieren.
Setup unter Windows, mit MSysGit1.6.3, entweder für DOS- oder Git-Bash-Session, mit DiffMerge oder KDiff3:
- setze ein Verzeichnis in deinen PATH (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 config auf Systemebene:
git config ---system core.autoCRLF=false
- Testen Sie, dass, wenn zwei Zeilen identisch sind (aber ihre EOL-Zeichen), sowohl DiffMerge als auch KDiff3 diese Zeilen während einer Zusammenführung ignorieren.
DOS-Skript (Anmerkung: die dos2unix-Befehl kommt von hier, und wird verwendet, um einen Unix-Eol-Stil zu simulieren. Dieser Befehl wurde in das am Anfang dieser Antwort erwähnte 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“) öffnet sich DiffMerge oder KDiff3, und Sie werden selbst sehen, welche Zeilen tatsächlich zusammengeführt und welche Zeilen ignoriert werden.
Warnung: Die Ergebnisdatei befindet sich immer im Windows-EOL-Modus (CRLF) mit DiffMerge …
KDiff3 bietet an, auf die eine oder andere Weise zu speichern.
Ich suchte nach der gleichen Antwort und fand es heraus Das
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 Merge-Konflikte zu vermeiden, kann git angewiesen werden, ein virtuelles Check-out und Check-in aller drei Stadien einer Datei durchzuführen, wenn ein Drei-Wege-Merge aufgelöst wird, indem die Konfigurationsvariable merge.renormalize gesetzt wird. Dadurch wird verhindert, dass Änderungen, die durch die Eincheck-Konvertierung verursacht wurden, falsche Zusammenführungskonflikte verursachen, wenn eine konvertierte Datei mit einer nicht konvertierten Datei zusammengeführt wird.
Solange „smudge→clean“ auch bei bereits verschmutzten Dateien zu derselben Ausgabe wie „clean“ führt, löst diese Strategie automatisch alle filterbezogenen Konflikte. Filter, die nicht auf diese Weise agieren, 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
Nach dem Lesen von https://stackoverflow.com/a/12194759/1441706 und https://stackoverflow.com/a/14195253/1441706
Für mich hat dieser Befehl den Trick perfekt gemacht:
git merge master -s recursive -X renormalize
Wie in dieser Antwort: https://stackoverflow.com/a/5262473/943928
Du könntest es versuchen: git merge -s recursive -Xignore-space-at-eol
Was ich getan habe, war, alles als Standard zu belassen (dh autocrlf=true), alle Dateien zu berühren (find . -exec touch {} \;), git sie als ‘geändert’ sehen zu lassen und sie zurückzugeben, und fertig. Sonst wirst du entweder immer wieder von lästigen Meldungen oder überraschenden Unterschieden geplagt oder musst alle Whitespace-Features von git abschalten.
Sie werden Schuldinformationen verlieren, aber es ist besser, es früher als später zu tun 🙂
“git merge -Xrenormalize” funktioniert wie ein Zauber.
Es scheint mir jetzt, dass der beste Weg darin besteht, die Zeilenenden auf beiden Zweigen zu normalisieren (und festzuschreiben), bevor sie zusammengeführt werden.
Ich habe “convert crlf to lf” gegoogelt und dies als erste Ergebnisse gefunden:
http://stahlforce.com/dev/index.php?tool=remcrlf
Ich habe es heruntergeladen und verwendet, scheint ein nettes Tool zu sein.
>sfk remcr . .py
Achten Sie jedoch darauf, ein Verzeichnis und einen Dateityp (z. B. .py) anzugeben, da sonst möglicherweise versucht wird, den Inhalt der Datei zu manipulieren .git
Verzeichnis!
Ach, ich wünschte. Dieses Zeilenende in Git ist total kaputt
– 1800 INFORMATIONEN
14. Mai 2009 um 7:54 Uhr
Es sieht nicht so aus, als könnte dies direkt durchgeführt werden, aber dieser Beitrag schlägt eine Problemumgehung vor. osdir.com/ml/git/2009-02/msg02532.html
– Dekan Smith
14. Mai 2009 um 8:03 Uhr
Soeben wurde ein Testfall hinzugefügt, der veranschaulicht, dass das Zusammenführungstool eines Drittanbieters den eol-Stil während einer Zusammenführung ignoriert
– VonC
14. Mai 2009 um 16:00 Uhr
stahlforce.com/dev/index.php?tool=remcrlf Ich habe es versucht, aber wenn Sie nach der letzten Zeile in Ihrem Code noch kein CRLF haben, fügt es von selbst ein LF hinzu und die Datei sieht in Git geändert aus. Ansonsten funktioniert es.
– Ameisenmann
24. Januar 2011 um 19:53 Uhr
Also, um zu verdeutlichen (nach dem, was ich feststellen kann): gibt es keine Möglichkeit, Git dazu zu bringen, CRs zu ignorieren, sich aber über alle anderen nachgestellten Leerzeichen zu beschweren?
– Stefan
31. Juli 2014 um 21:56 Uhr