Gibt es eine git-merge --dry-run Option?


725

Ich verschmelze in einem Remote-Zweig, der möglicherweise viele Konflikte aufweist. Wie kann ich feststellen, ob es Konflikte geben wird oder nicht?

Ich sehe so etwas wie ein --dry-runOn nicht git-merge.


5
Da das Verzweigen mit Git billig ist, können Sie eine Kopie auschecken und dann keinen Probelauf durchführen. Sie können die Kopie anschließend einfach wegwerfen.
Alexander Mills

Antworten:


812

Übergeben Sie, wie bereits erwähnt, das --no-commitFlag, aber um ein schnelles Vorwärts-Commit zu vermeiden, übergeben Sie es auch --no-ffwie folgt:

$ git merge --no-commit --no-ff $BRANCH

So untersuchen Sie die inszenierten Änderungen:

$ git diff --cached

Und Sie können die Zusammenführung rückgängig machen, auch wenn es sich um eine Schnellvorlaufzusammenführung handelt:

$ git merge --abort

51
Das ist großartig, wird aber Ihre Arbeitskopie trotzdem ändern. Wenn Ihr Repo ein Live-Webserver ist, können Sie Dateien mit Konflikten in
liefern

21
Sie können eine Zusammenführung nicht wirklich durchführen, ohne die Arbeitskopie zu beeinträchtigen.
Mipadi

55
Stimmt, aber so etwas wie git merge --only-if-there-wont-be-any-conflictsoder git diff --show-conflicts <commit>wäre wirklich praktisch. Schade, dass es noch nicht möglich ist oder fehlt mir etwas?
Dave1010

344
@ dave1010 Du solltest niemals Zusammenführungen auf einem Live-Webserver durchführen !!! Dafür ist Ihre Entwicklungsbox da! Korrigieren Sie den Zweig "prod" und schieben Sie ihn dann auf den echten Webserver.
jpswain

52
Wenn Sie auf einem Live- / Produktionsserver arbeiten, möchten Sie nie etwas anderes tun als git pull --ff-only!
ThiefMaster

237

Ich musste nur eine Methode implementieren, die automatisch Konflikte zwischen einem Repository und seiner Fernbedienung findet. Diese Lösung führt die Zusammenführung im Speicher durch, sodass weder der Index noch der Arbeitsbaum berührt werden. Ich denke, dies ist der sicherste Weg, um dieses Problem zu lösen. So funktioniert das:

  1. Holen Sie die Fernbedienung in Ihr Repository. Zum Beispiel: git fetch origin master
  2. Führen Sie git merge-base aus: git merge-base FETCH_HEAD master
  3. Führen Sie den Git-Merge-Tree aus: git merge-tree mergebase master FETCH_HEAD( Mergebase ist die hexadezimale ID, die die Merge-Basis im vorherigen Schritt gedruckt hat.)

Angenommen, Sie möchten den Remote-Master mit Ihrem lokalen Master zusammenführen, können jedoch beliebige Zweige verwenden. git merge-treeführt die Zusammenführung im Speicher aus und druckt das Ergebnis in die Standardausgabe. Grep für das Muster <<oder >>. Oder Sie können die Ausgabe in eine Datei drucken und dies überprüfen. Wenn Sie eine Zeile finden, die mit "in beiden geändert" beginnt, liegt höchstwahrscheinlich ein Konflikt vor.


41
Diese Antwort wird meiner Meinung nach viel unterschätzt, da es sich um eine saubere Lösung handelt, ohne die Arbeitskopie oder den Index zu berühren.
Sschuberth

23
Übrigens können die Schritte 2 und 3 mithilfe des Backtick-Operators der Linux-Konsole, der den Inhalt git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
direkt

15
Zu [alias] in .gitconfig hinzufügen: dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "#check, wie die Zusammenführung von dev mit master verlaufen wird: git dry Dev Master
Noel

8
Meine neue Lieblings-GIT-Linie: git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"Einfach großartig! +100
Rudie

4
Beim Testen habe ich festgestellt, dass die Suche nach "In beiden geändert" -Flags zusammengeführt wird, wobei beide Zweige dieselbe Datei ändern, auch wenn sie nicht zu einem Zusammenführungskonflikt führen. Um nur tatsächliche Konflikte zu identifizieren, musste ich nach dem Konflikt-Markup suchen, das wie folgt beginnt: +<<<<<<< .ourAlso verwende ich einen Grep-Ausdruck wiegrep -q '^+<* \.our$'
Guy

55

Meine einfache Brute-Force-Lösung hierfür lautet:

  1. Erstellen Sie einen "Pre-Master" -Zweig (vom Master natürlich)

  2. Füge alle Dinge, die du willst, in diesen Pre-Master ein.
    Dann können Sie sehen, wie die Zusammenführung stattgefunden hat, ohne den Master zu berühren.

    • Pre-Master in Master OR zusammenführen
    • Füge alle von Möchtegern freigegebenen Zweige zum Master zusammen

Wie auch immer, ich würde dem Rat von @ orange80 folgen.


5
Ich mag die @akostajti-Lösung, aber dies ist eine weitere unterschätzte Option. Tatsächlich ziehe ich es vor, defensiv zu sein und einen neuen temporären Zweig zu erstellen (natürlich nur, wenn ich Konflikte erwarte, sonst ist es ein Overkill), und wenn etwas schief geht, löschen Sie ihn einfach.
Jakub.g

1
Keine Ahnung, ob dies eine "schmutzige" Lösung ist oder nicht, aber es macht wirklich den Job. Ich mag das! (Y)
Sara

3
Dies sollte die akzeptierte Lösung sein, imo. Es ist schnell, einfach, sicher, umkehrbar, intuitiv und solange es keine nicht festgeschriebenen Änderungen gibt, bevor Sie beginnen, hat es keine Nebenwirkungen.
Bob Ray

3
Diese Lösung sagt Ihnen, dass Sie nicht verstehen, wie Git funktioniert. Verzweigungen sind nur Zeiger und Sie erstellen nur einen redundanten Zeiger. Sie haben das schlechte Gefühl, dass Sie Ihren Zweig irgendwie verletzen können, aber Sie können nicht. Sie können immer tun, git merge --abortwenn es Konflikte gibt, git reset --hard HEAD~1wenn es eine Zusammenführung gab oder git reset --hard origin/master. Das Erstellen eines weiteren Zweigs gibt Ihnen ein Gefühl der Sicherheit, aber wenn Sie lernen, wie Git funktioniert, werden Sie verstehen, dass es sich um fehlgeleitete Angst handelt. Wenn Bedenken bestehen, die Arbeitskopie nicht zu ändern, bietet dies keine Lösung.
Thibault D.

@ thibault-d Überlegen Sie, wie komplex die Lösung ist, wenn Sie nicht mit einem sauberen Zweig beginnen. git merge --no-commitEine Zusammenführung wird nicht abgebrochen, wenn sie schnell weitergeleitet werden kann. git merge --abortfunktioniert nicht, wenn es zusammengeführt wurde. Wenn Sie dies als Skript schreiben möchten, ist dies umständlich, da Sie git mergenicht mit ausreichend guten Fehlercodes antworten, um die verschiedenen Arten von Konflikten zu erklären. Das Arbeiten mit einem neuen Zweig verhindert, dass ein defektes Skript Ihr Repo in einem Zustand belässt, in dem manuelle Eingriffe erforderlich sind. Sicher kannst du nichts verlieren. Aber es ist einfacher, anders zu bauen.
Erik Aronesty

47

Das Rückgängigmachen einer Zusammenführung mit git ist so einfach, dass Sie sich nicht einmal Gedanken über den Trockenlauf machen sollten:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

BEARBEITEN: Wie in den Kommentaren unten angegeben, möchten Sie Änderungen in Ihrem Arbeitsverzeichnis oder Staging-Bereich wahrscheinlich vor dem oben beschriebenen Vorgang aufbewahren (andernfalls verschwinden sie nach den git resetobigen Anweisungen).


7
Um einfach zu überprüfen, ob eine Zusammenführung schnell vorspult (FF), müssen Sie die Liste von git branch --contains HEADoder noch direkter überprüfen. Verwenden Sie einfachgit merge --ff-only
Brian Phillips

7
git reset --hard ist einer der wenigen Befehle zum Löschen von Informationen ohne Backout, die git hat, und sollte daher mit äußerster Vorsicht verwendet werden. Als solches -1
Kzqai

8
@Tchalvak gibt es noch Reflog.
Kissaki

3
--dry-runwürde nicht "einfach prüfen, ob eine Zusammenführung schnell vorwärts geht". Es würde die genaue Ausgabe zurückgeben, die eine Zusammenführung ergeben würde: Dateien, Konflikte usw. Ob es ff ist, ist nicht wirklich interessant, oder?
Rudie

3
wie wäre es git stash; git reset --hard? @ BrianPhillips
Code Whisperer

41

Ich habe einen Alias ​​dafür gemacht und arbeite wie ein Zauber, ich mache das:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

Jetzt rufe ich einfach an

git mergetest <branchname>

Um herauszufinden, ob es Konflikte gibt.


Brillant! Ich behalte das.
qbert65536

28

Vergleichen Sie einfach Ihren aktuellen Zweig mit dem Remote-Zweig. Hier erfahren Sie, was sich beim Ziehen / Zusammenführen ändern wird.

#see diff between current master and remote branch
git diff master origin/master

1
Interessante Idee. Wie würde ich diese Ausgabe betrachten und feststellen, ob die Zusammenführung funktionieren wird oder nicht?
MatrixFrog

6
Dies sagt Ihnen nicht, ob Konflikte auftreten werden ... aber es gibt Ihnen eine allgemeine Vorstellung davon, was passieren wird, wenn Sie ein Pull / Merge durchgeführt haben.
Timh

10
Dies zeigt Ihnen nur den Unterschied zwischen den beiden Zweigen und nicht das Ergebnis der Zusammenführung. Dies ist eine wichtige Unterscheidung, da beim Zusammenführen in einigen Fällen automatisch Änderungen aus verschiedenen Zweigen vorgenommen werden, je nachdem, wann sie festgeschrieben wurden. Wenn Sie also einen Unterschied machen, denken Sie möglicherweise, dass einige Ihrer Änderungen rückgängig gemacht werden, wenn der Zusammenführungsprozess in Wirklichkeit automatisch neuere Änderungen gegenüber älteren Änderungen übernimmt. Hoffe das macht Sinn.
Markquezada

3
Um auf dem Kommentar von @ mirthlab aufzubauen, gibt es einen signifikanten Unterschied zwischen diff und merge, wenn jemand zuvor eine Zusammenführung mit der Zusammenführungsstrategie "our" (oder anderen manuellen Zusammenführungskorrekturen) durchgeführt hat. Der Diff zeigt Ihnen auch Unterschiede an, die bereits als "zusammengeführt" gezählt werden.
Tao

21

Ich benutze dazu den Befehl request-pull git. Sie können jede Änderung sehen, die beim Zusammenführen auftreten würde, ohne jedoch etwas in Ihren lokalen oder Remote-Repositorys zu tun .

Stellen Sie sich zum Beispiel vor, Sie möchten einen Zweig mit dem Namen "feature-x" in Ihren Hauptzweig einbinden

git request-pull master origin feature-x

zeigt Ihnen eine Zusammenfassung dessen, was passieren würde (ohne etwas zu tun):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

Wenn Sie den -pParameter hinzufügen , erhalten Sie auch den vollständigen Patch-Text, genau wie wenn Sie für jede geänderte Datei einen Git-Diff ausführen würden.


3
Sie könnten dies etwas klarer machen, indem Sie hinzufügen, was masterund originwas in den Befehlszeilenoptionen zu tun ist, und was ist, wenn ich mich beispielsweise in einem lokalen Zweig befinde branch1und request-pulleinen Zweig in einem lokalen Feature ausführen möchte branch2? Muss ich noch brauchen origin? Natürlich kann man die Dokumentation immer lesen.
Ela782

Leider funktioniert dieser Befehl nur, wenn Rev # 2 ein Zweigname ist, es funktioniert nicht für Hashes: /
Jared Grubb

20

Ich bin überrascht, dass noch niemand vorgeschlagen hat, Patches zu verwenden.

Angenommen, Sie möchten eine Zusammenführung von your_branchin testen master(ich gehe davon aus, dass Sie masterausgecheckt haben):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

Das sollte den Trick machen.

Wenn Sie Fehler wie erhalten

error: patch failed: test.txt:1
error: test.txt: patch does not apply

Das bedeutet, dass der Patch nicht erfolgreich war und eine Zusammenführung zu Konflikten führen würde. Keine Ausgabe bedeutet, dass der Patch sauber ist und Sie den Zweig problemlos zusammenführen können


Beachten Sie, dass dies Ihren Arbeitsbaum nicht wirklich ändert (abgesehen von der Erstellung der Patch-Datei natürlich, aber Sie können diese anschließend sicher löschen). Aus der git-apply-Dokumentation:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

Hinweis für alle, die klüger / erfahrener mit Git sind als ich: Bitte lassen Sie mich wissen, wenn ich hier falsch liege und diese Methode ein anderes Verhalten zeigt als eine reguläre Zusammenführung. Es scheint seltsam, dass in den mehr als 8 Jahren, in denen diese Frage existiert hat, niemand diese scheinbar offensichtliche Lösung vorschlagen würde.


Diese Methode ist die akzeptierte Antwort auf diese Frage und es gibt einige Einschränkungen in den Kommentaren, wie "Git konnte die 'rekursive' Zusammenführungsstrategie nicht verwenden" und "Patch-Datei gibt Fehler für neue Dateien". Ansonsten scheint es toll.
Neno

1
Ein kürzerer Weg, ohne eine temporäre Patch-Datei zu erstellen : git diff master your_branch | git apply --check.
ks1322

9

Dies könnte interessant sein: Aus der Dokumentation:

Wenn Sie eine Zusammenführung versucht haben, die zu komplexen Konflikten geführt hat, und von vorne beginnen möchten, können Sie mit git merge --abort wiederherstellen .

Sie können es aber auch naiv (aber langsam) machen:

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(Hinweis: Es funktioniert nicht nur beim Klonen nach / tmp. Sie benötigen eine Kopie, um sicherzustellen, dass nicht festgeschriebene Änderungen nicht in Konflikt geraten.)


2
Wenn alles , was Sie brauchen , ist ein Hammer ... :) 1
kaiser

Saubere Kopie kann mit erhalten werden cp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(für eine gute Maßnahme), git status(um zu überprüfen , dass es sauber).
ADTC

8

Mir ist bewusst, dass dies eine alte Frage ist, aber es ist die erste, die in einer Google-Suche angezeigt wird.

Git hat beim Zusammenführen die Option --ff-only eingeführt.

Von: http://git-scm.com/docs/git-merge


--ff-only

Verweigern Sie das Zusammenführen und Beenden mit einem Status ungleich Null, es sei denn, der aktuelle HEAD ist bereits auf dem neuesten Stand oder die Zusammenführung kann als schneller Vorlauf aufgelöst werden.

Wenn Sie dies tun, wird versucht, zusammenzuführen und vorzuspulen. Wenn dies nicht möglich ist, werden Sie abgebrochen und aufgefordert, den schnellen Vorlauf nicht durchzuführen, aber Ihr Arbeitszweig bleibt unberührt. Wenn es schnell vorspulen kann, führt es die Zusammenführung in Ihrem Arbeitszweig durch. Diese Option ist auch am verfügbar git pull. Sie können also Folgendes tun:

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
Das führt die Zusammenführung durch, wenn dies mit einem schnellen Vorlauf möglich ist, was ich in der ursprünglichen Frage nicht wollte. Ich denke, die akzeptierte Antwort hat die andere Hälfte, die das Problem behebt.
Otto

Wirklich, aber ausgefallene Git-Eingabeaufforderungen machen das, was ich für solche Dinge habe, überflüssig.
Otto

2
Es ist nicht wirklich dasselbe. Das Beenden mit einem Status ungleich Null, da die Zusammenführung nicht aufgelöst werden kann, da der schnelle Vorlauf nicht bedeutet, dass Konflikte vorliegen . Es bedeutet nur, dass die Historie auseinander gegangen ist und ein Zusammenführungs-Commit erforderlich ist.
ADTC

7

Ich verwende das Git-Protokoll, um zu sehen, was sich an einem Feature-Zweig vom Master-Zweig geändert hat

git log does_this_branch..contain_this_branch_changes

zB - um zu sehen, welche Commits sich in einem Feature-Zweig befinden, der zum Master zusammengeführt wurde / nicht:

git log master..feature_branch

3

Wenn Sie von B nach A vorspulen möchten, müssen Sie sicherstellen, dass das Git-Protokoll B..A Ihnen nichts anzeigt, dh A hat nichts, was B nicht hat. Aber selbst wenn B..A etwas hat, können Sie möglicherweise immer noch ohne Konflikte zusammengeführt werden. Das Obige zeigt also zwei Dinge: dass es einen schnellen Vorlauf geben wird und Sie somit keinen Konflikt bekommen.


2

Meine Lösung besteht darin, rückwärts zu verschmelzen.

Anstatt Ihren Zweig mit dem entfernten "Ziel" -Zweig zusammenzuführen, führen Sie diesen Zweig mit Ihrem Zweig zusammen.

git checkout my-branch
git merge origin/target-branch

Sie werden sehen, ob es Konflikte gibt, und können planen, wie diese gelöst werden können.

Danach können Sie entweder die Zusammenführung über Git abbrechen merge --abortoder (wenn keine Konflikte aufgetreten sind und eine Zusammenführung stattgefunden hat) zum vorherigen Festschreiben über zurücksetzengit reset --hard HEAD~1


-2

Erstellen Sie eine temporäre Kopie Ihrer Arbeitskopie, fügen Sie diese dann zusammen und unterscheiden Sie die beiden.

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.