Git - wie man einen Zusammenführungskonflikt und eine manuelle Zusammenführung für eine ausgewählte Datei erzwingt

82

Wir unterhalten Webanwendungen mit einem gemeinsamen Hauptzweig und vielen parallelen Zweigen, einer für jede Installation, die jeweils nur wenige spezifische Änderungen aufweisen. Der Quellcode wird in Git verwaltet und ist ein hervorragendes Tool, wenn wir Funktionen und Bugfixes vom Hauptzweig in parallele übertragen möchten. Es gibt jedoch nur wenige Dateien, die sensibel sind, und das automatische Zusammenführen führt normalerweise zu schlechten Ergebnissen. Das Zusammenführen wäre also viel einfacher, wenn sie irgendwie markiert werden könnten und jede Zusammenführung zu Konflikten führen würde, die eine manuelle Zusammenführung erfordern.

Ich suchte nach einer Antwort:

  1. Ich verwende die Zusammenführungsoptionen --no-commit und --no-ff , aber es ist nicht dasselbe.
  2. Hier und hier stellt jemand die gleiche Frage, aber ohne Lösung.
  3. Ein ähnlicher Fall scheint zu sein, wie verhindert werden kann , dass Dateien mit .gitattributes zusammengeführt werden, die Folgendes enthalten: somefile.php merge = our . Ich habe versucht, eine Zusammenführungsoption zu finden, die zu Konflikten führen oder die manuelle Zusammenführung erzwingen würde, aber bisher keine gefunden.
  4. .gitattributes, die Folgendes enthalten: somefile.php -merge wird niemals automatisch zusammengeführt und erzwingt daher die manuelle Zusammenführung. Es ist eine 90% ige Lösung, aber ich versuche, die automatische Zusammenführung zu versuchen und sie als Konflikt zu markieren, unabhängig davon, ob sie erfolgreich ist oder nicht. Dies ist jedoch der Lösung bisher am nächsten. (... danke Charles Bailey für die Klarstellung ...)
  5. Jemand schlägt vor, einen benutzerdefinierten Zusammenführungstreiber ( 1 , 2 ) zu schreiben , aber wie das geht, ist mir alles andere als klar.

bearbeiten: Variante 4. Beschreibung

Stepan
quelle
6
Dies wäre nicht die genaue Antwort, nach der Sie suchen, aber aus dem gleichen Grund, den ich git fetchzuerst mache und dann verwende git difftool <file> FETCH_HEAD, damit ich die Änderung in der Remote-Verzweigung manuell auf die lokale anwenden kann.
MHC
MHC: Dies ist ein netter Trick (insbesondere, wenn er für jeden parallelen Zweig im Skript gespeichert wird + kombiniert mit der Verhinderung der automatischen Zusammenführung von Dateien). Der Hauptnachteil besteht darin, dass im Team-Workflow die Wahrscheinlichkeit besteht, dass jemand diesen Schritt vergisst und stattdessen nur eine normale Zusammenführung vornimmt.
Stepan
2
Die Einstellung -mergehindert Sie nicht daran, die Dateien zusammenzuführen, sondern zwingt Sie lediglich dazu, dies manuell zu tun, z. B. mit einem Mergetool. Ist es nicht das, was du brauchst?
CB Bailey
Es sind 90% von dem, was ich will. Ich möchte, dass die Zusammenführung automatisch erfolgt, aber für diese vertrauliche Datei wird die Zusammenführung als Konflikt betrachtet, auch wenn keine vorhanden ist, sodass jedes Mal eine manuelle Überprüfung erzwungen wird.
Stepan
@Stepan Ich bin in einer ähnlichen Situation, also möchte ich etwas klarstellen. Was Sie sagen, dass mit -mergein .gitatttributes git mergenichts bewirkt und alle Arbeiten mit dem Merge-Tool erledigt werden müssen? Es gibt also kein <<<<< ===== >>>> für das Merge-Tool, oder? Und Dans Lösung bietet dies?
Nero Gris

Antworten:

59

Option 5, ein benutzerdefinierter Zusammenführungstreiber, ist wahrscheinlich der Weg, um dem, was Sie wollen, am nächsten zu kommen. Es ist überraschend einfach zu tun. Im Folgenden finden Sie ein Beispiel für eines, das Sie meiner Meinung nach dem gewünschten Verhalten ziemlich nahe bringen sollte.

Erstellen Sie zunächst ein Merge-Treiberskript mit dem Namen merge-and-verify-driver. Machen Sie es ausführbar und platzieren Sie es an einem geeigneten Ort (Sie können dieses Skript auch in das Repo einchecken, da die Konfigurationsdatei des Repos davon abhängt). Git wird dieses Shell-Skript ausführen, um die Zusammenführung der vertraulichen Dateien durchzuführen:

#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

Dies führt nur das Standard-Zusammenführungsverhalten aus, das Git selbst normalerweise ausführt. Der Hauptunterschied besteht darin, dass das Skript immer einen Wert ungleich Null zurückgibt (um anzuzeigen, dass ein Konflikt aufgetreten ist, auch wenn die Zusammenführung tatsächlich ohne Konflikte gelöst wurde).

Als Nächstes müssen Sie Git über die Existenz Ihres benutzerdefinierten Zusammenführungstreibers informieren. Sie tun dies in der Konfigurationsdatei des Repos ( .git/config):

[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

In diesem Beispiel habe ich merge-and-verify-driverdas oberste Verzeichnis des Repos ( ./) abgelegt . Sie müssen den Pfad zum Skript entsprechend angeben.

Jetzt müssen Sie den vertraulichen Dateien nur noch die richtigen Attribute zuweisen, damit beim Zusammenführen dieser Dateien der benutzerdefinierte Zusammenführungstreiber verwendet wird. Fügen Sie dies Ihrer .gitattributesDatei hinzu:

*.sensitive merge=verify

Hier habe ich Git gesagt, dass jede Datei mit einem Namen, der dem Muster entspricht *.sensitive, den benutzerdefinierten Zusammenführungstreiber verwenden sollte. Natürlich müssen Sie ein Muster verwenden, das für Ihre Datei (en) geeignet ist.

Dan Moulding
quelle
Vielen Dank für diese ausführliche Anleitung!
Stepan
13
Es scheint, dass der Zusammenführungstreiber in "offensichtlichen" Lösungen nicht aufgerufen wird. Wenn die Datei beispielsweise nur in einem Zweig geändert wurde und Sie eine Zusammenführung durchführen, wird die "vertrauliche" Datei überschrieben und der Zusammenführungstreiber wird nicht aufgerufen. Gibt es eine Möglichkeit, das zu beheben?
VitalyB
Würde sich das wirklich so verhalten, wie es @VitalyB vorschlägt? Vielen Dank!
Filippo
1
Dies funktioniert, aber gibt es eine Möglichkeit, dies zu einer globalen Option für alle Repositorys auf einem Computer zu machen? Auch eine Möglichkeit, es über die Befehlszeile aufzurufen? Ich wünschte, es gäbe eine Möglichkeit, dies so einfach wie das Ändern der Zusammenführungsstrategie in der Befehlszeile zu tun.
user1748155
4
Hinzufügen zu @VitalyB Kommentar. Die Zusammenführung wird auch nicht angezeigt, wenn beide Zweige dieselbe Änderung an einer Datei vorgenommen haben. Zum Beispiel haben beide Zweige die Version um 1 erhöht, und Sie möchten beim Zusammenführen um 2 erhöhen ... Sehr praktisches Problem, noch ungelöst .: (
VasiliNovikov
1

Diese beiden Befehle scheinen den gleichen Effekt zu haben wie die Verwendung des benutzerdefinierten Zusammenführungstreibers:

git merge --no-commit your_target_branch
git checkout --conflict merge .   (do not forget the . and run it in the top dir of the repository)

Der erste Befehl stoppt die Zusammenführung vor dem Erstellen des Zusammenführungs-Commits, und der zweite Befehl markiert alle in den beiden Zweigen geänderten Dateien als zu lösenden Konflikt, auch wenn ursprünglich kein Konflikt bestand.

Louisiuol
quelle
Ich mag die Idee einer "einmaligen" Lösung (ich bin gerade auf einen solchen Fall gestoßen), aber das hat bei mir nicht funktioniert. Git hat ein FF durchgeführt, was zu einer schlechten Zusammenführung führte (es war im Wesentlichen und unsere Zusammenführung).
Nero Gris
@Nerogris In der Tat wird es nicht für Zusammenschlüsse mit schnellem Vorlauf funktionieren. Sie können jederzeit die Option --no-ff hinzufügen, aber der zweite Befehl führt zu keinem Konflikt, da in einem der beiden Zweige der Zusammenführung keine Änderungen gegenüber dem gemeinsamen Vorfahren vorgenommen wurden.
Louisiuol
Ich habe ff in meiner globalen Konfiguration auf false gesetzt. Als ich sagte, es sei eine FF-Fusion, meine ich, wenn ich Git nicht gesagt hätte, dass er diese nicht machen soll, hätte es das getan.
Nero Gris
0

Hinweis: Dieser Artikel " Schreiben eines Git-Merge-Treibers für PO-Dateien " veranschaulicht die Art der Manipulation, die Sie beim manuellen Zusammenführen einer Datei durchführen können: Sie können sie vorverarbeiten, damit für die manuelle Zusammenführung bestimmte Daten bereitstehen.

git merge-filekann zum Beispiel verwendet werden, um Dateien vor dem Zusammenführen (!) zu entschlüsseln (und neu zu verschlüsseln ).

In Ihrem Fall stellen Sie beim Beenden Ihres Zusammenführungstreibers mit einem Status ungleich 0 sicher, dass die Zusammenführung manuell erfolgt.

VonC
quelle
2
Könnten Sie den Link "Treiber für PO-Dateien zusammenführen" näher erläutern, da dies anscheinend dazu führt, dass mir der Zugriff verweigert wird? Ich hoffe, es würde eine Antwort auf die Frage stackoverflow.com/questions/16214067/…
Mikko Rantalainen
@MikkoRantalainen bei der Arbeit blockiert, also werde ich es heute Abend von zu Hause aus versuchen.
VonC
1
Der "Merge-Treiber für PO-Dateien" funktioniert auch bei mir nicht :(
sampablokuper
1
@sampablokuper Ich stimme zu: Der Artikel ist für "nicht autorisierte" Leser gesperrt. Ich würde nicht wissen warum.
VonC
1
@sampablokuper Ich habe momentan keinen Zugriff auf diesen Blog. Ich werde weiter nach seinem Inhalt suchen.
VonC