2014-10-24 2 views
9

Ich verwende den folgenden Befehl ein Patch in Mercurial anzuwenden, ohne sie zu begehen:Wie man mehrere Flecken unter Verwendung der hg Befehlszeile anwendet, wenn es bereits nicht festgeschriebene Änderungen gibt?

hg import patch.diff --no-commit 

Es funktioniert großartig, aber wenn ich mehrere Patches auf einmal wie diese anzuwenden versuchen:

hg import patch1.diff --no-commit 
hg import patch2.diff --no-commit 
... 

I erhalten diese Fehlermeldung nach der zweiten commit:

abort: uncommitted changes 

Wenn ich genau in SourceTree das gleiche tun (um die patch1 gelten dann Patch 2 und wählen Sie "Ändern Arbeitskopie Dateien") es funktioniert: die beiden Patches sind auf der Arbeitskopie angewendet, Änderungen von Patch1 und Patch2 kombiniert/zusammen gefaltet.

Wie das gleiche mit der hg-Befehlszeile zu tun?

Antwort

10

Dies ist das Verhalten, das von den Mercurial-Autoren entwickelt wurde: Stellen Sie sich vor, dass Sie Änderungen an einer Arbeitskopie "manuell" vorgenommen haben, wir würden nicht hg import automatisch den Patch anwenden und sowohl Ihre Änderungen als auch den Patch festschreiben ändert sich mit einer falschen Protokollmeldung und beide Änderungen verschränken sich.

Aus diesem Grund ist die hg help import sagt:

Because import first applies changes to the working directory, import will 
abort if there are outstanding changes. 

Der Importbefehl mehr für den Import von Changesets ist (mit metedata wenn die Daten von hg export kommt) als nur Einspielen von Patches. Wenn Sie eigene Änderungen in der Arbeitskopie haben, können Sie beispielsweise weiterhin hg import --bypass verwenden und es wird dort kein Fehler auftreten, da das Commit direkt auf das Repository und nicht auf die Arbeitskopie angewendet wird. (Hinweis: Aber wenn Sie nur Ihre Änderungen bestätigen, erhalten Sie zwei Köpfe, die Sie zusammenführen müssen .. :-).

Eine Lösung mit der Kommandozeile für Unix-Systeme ist die direkte Verwendung des Befehls patch anstelle von hg import, da dann keine Überprüfung von lokalen Änderungen durchgeführt wird. ZB

for i in 1 2 etc. 
do 
    patch -p1 < patch$i.diff 
done 
hg commit ... 

Für Nicht-Unix-Systeme können Sie auch eine reine Mercurial Lösung haben durch die shelve Erweiterung zu installieren, ist es in Ihrer globalen Konfigurationsdatei (Mercurial.ini) ermöglicht, und shelve dann die Verschmelzungen zu handhaben verwenden ein Patch nach dem anderen:

hg import --no-commit patch1.diff 
hg shelve 
hg import --no-commit patch2.diff 
hg unshelve 
etc. 

Wenn überhaupt würde ein Konflikt auftreten, shelve wird es erkennen und Sie lösen würden, um es dann shelve sagen, dass es mit der --continue Option gelöst.

Ich hoffe, es wird helfen.

+0

über' patch' Befehl: ich habe keine solche Dienstprogramm habe in meinem Quecksilber-Ordner (Windows), reden Sie 'hg Patch'? Wenn ja, habe ich es schon ausprobiert, bevor ich diese SO Frage gestellt habe und sie nur die gleiche Fehlermeldung wie "hg import" gemeldet habe. – tigrou

+0

Es scheint ein 'Linux' Dienstprogramm zu sein, vielleicht installiert' cygwin' es. – tigrou

+0

Ich wusste nicht, dass Sie nicht mit Unix arbeiten, ja 'Patch' ist ein Unix-Programm. Sie können entweder: eine Cygwin-Version verwenden, kopieren, wie Sie erwähnt haben, oder ich denke, Sie können eine "pure-hg" -Lösung haben, ich werde es zu meiner Antwort hinzufügen ..;) –

4

Hier ist, was für mich (Fenster-Lösung) arbeitete, wurde Idee packte aus Christophe Muller Antwort:

copy /b "patch01.diff" + "patch02.diff" + ... + "patchXX.diff" "all.diff" 

hg import "all.diff" --no-commit 

Es ist einfach verketten alle Patches zusammen (als eine große Datei) dann anwenden.

2

Eine mögliche Lösung ist die Verwendung Mercurial Queues (beachten Sie - es scheint, dass diese Erweiterung "oft für die Abwertung gilt", aber es ist noch nicht veraltet, und kommt mit Mercurial vorinstalliert).

Wenn Sie MQ noch nicht verwendet haben, ist es sehr praktisch, wenn es ein wenig komplex ist. Aber es erlaubt effektiv Sie Warteschlangen von Patches zu erstellen, die geschoben werden können, knallte, nachbestellt usw.

Sie könnten es verwenden, um Ihr Problem zu lösen, wie so:

:: if you don't already have MQ initialised for the repo, do so 
hg init --mq 

:: import the patches you want as queue entries 
hg qimport -P patch1.diff 
hg qimport -P patch2.diff 
hg qimport -P patch3.diff 

The -P Option Die Änderungen werden beim Importieren übernommen, was bedeutet, dass Sie effektiv prüfen, ob sie korrekt angewendet werden. Wenn Sie alle Patches in MQ importiert haben, Pop sie alle (so keine angewendet werden und Sie sind wieder da, wo Sie begonnen haben), und klappen sie alle in eine neue, kombinierte Patch:

:: go back to no patches applied, and create a new patch at the front of the queue 
hg qpop --all 
hg qnew -m "Your planned commit message" combined_patches 
:: fold the named patches into the current one 
hg qfold patch1 patch2 patch3 

Dann Sie, wenn ‚re glücklich mit dem resultierenden Patch, nur wandelt sie in einen‚echten‘changeset:

:: convert combined_patches into a "real" changeset 
hg qfinish combined_patches 
+0

Mercurial Queues wird mit Mercurial verteilt, aber nicht standardmäßig aktiviert. Wenn Sie sich fragen, warum es oft für die Ablehnung gilt: http://gregoryszorc.com/blog/2014/06/23/please-stop-using-mq/ – Mathiasdm

+0

@Mathiasdm: Ah, ich muss es aktiviert haben ich dann :) - und ja, ich habe gerade diesen Artikel gerade gelesen. – icabod

Verwandte Themen