it-swarm.com.de

Wie wende ich mehrere Patches über die hg-Befehlszeile an, wenn bereits nicht festgeschriebene Änderungen vorliegen?

Ich verwende den folgenden Befehl, um einen Patch in Mercurial anzuwenden, ohne ihn festzuschreiben:

hg import patch.diff --no-commit

Es funktioniert jedoch hervorragend, wenn ich versuche, mehrere Patches gleichzeitig anzuwenden:

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

Ich erhalte diese Fehlermeldung nach dem zweiten Commit:

abort: uncommitted changes

Wenn ich in SourceTree genau dasselbe mache (um Patch1 und dann Patch2 anzuwenden und "Arbeitskopiedateien ändern" zu wählen), funktioniert es: Die beiden Patches werden auf die Arbeitskopie angewendet, Änderungen von Patch1 und Patch2 werden kombiniert/zusammengefaltet.

Wie mache ich das gleiche mit hg Kommandozeile?

14
tigrou

Dies ist das Verhalten, das von den Mercurial-Autoren entwickelt wurde: Stellen Sie sich vor, Sie hätten nicht festgeschriebene Änderungen in einer Arbeitskopie "manuell" vorgenommen. Wir möchten nicht, dass hg import den Patch automatisch anwendet und sowohl Ihre Änderungen als auch die Patch-Änderungen mit einem Fehler begehen Protokollnachricht und beide Änderungen miteinander verwickelt.

Deshalb sagt der hg help import:

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

Der Importbefehl ist mehr für das Importieren von Änderungssätzen (mit Metadaten, wenn die Daten aus hg export stammen), als nur Patches anzuwenden. Wenn Sie Ihre eigenen Änderungen an der Arbeitskopie haben, können Sie beispielsweise noch hg import --bypass verwenden, und dort wird kein Fehler angezeigt, da das Commit direkt auf das Repository und nicht auf die Arbeitskopie angewendet wird. (Hinweis: Wenn Sie jedoch nur Ihre Änderungen festschreiben, erhalten Sie zwei Köpfe, die Sie zusammenführen müssen. :-).

Eine Lösung mit der Befehlszeile für Unix-Systeme besteht darin, den Befehl patch direkt anstelle von hg import zu verwenden, da dann keine Überprüfung der lokalen Änderungen durchgeführt wird. Z.B.,

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, indem Sie die Erweiterung shelve installieren, in Ihrer globalen Konfigurationsdatei (Mercurial.ini) aktivieren und dann shelve verwenden, um die Zusammenführungen Patches nach dem anderen zu behandeln:

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

Wenn jemals ein Konflikt auftreten würde, wird shelve ihn erkennen und Sie müssten ihn lösen, dann sagen Sie shelve, dass er mit der --continue-Option gelöst wird.

Ich hoffe es hilft.

13

Folgendes funktionierte für mich (Windows-Lösung), Idee wurde aus Christophe Muller answer gezogen:

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

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

Es werden einfach alle Patches zusammengefügt (als eine große Datei) und anschließend angewendet.

4
tigrou

Eine mögliche Lösung ist die Verwendung von Mercurial Queues (Hinweis: Diese Erweiterung wird anscheinend als "oft als veraltet angesehen" angesehen, ist aber noch nicht veraltet und wird mit Mercurial vorinstalliert).

Wenn Sie MQ noch nicht verwendet haben, ist es sehr praktisch, wenn es etwas komplex ist. Sie können jedoch effektiv Warteschlangen von Patches erstellen, die verschoben, geknickt, neu angeordnet usw. werden können.

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

:: 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

Mit der -P-Option werden die Änderungen beim Import übernommen. Das bedeutet, dass Sie effektiv prüfen, ob sie korrekt angewendet werden. Wenn Sie alle Patches in MQ importiert haben, lassen Sie sie alle (so dass keine angewendet werden und Sie wieder zurück sind.) wo Sie angefangen haben), und falten Sie sie alle zu einem neuen, kombinierten 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

Wenn Sie mit dem resultierenden Patch zufrieden sind, konvertieren Sie es einfach in eine "echte" Änderungsmenge:

:: convert combined_patches into a "real" changeset
hg qfinish combined_patches
2
icabod

Ich denke, es könnte einen eleganteren Weg geben, dies zu tun:

(wenn Sie zuerst ein Reverse-Patch extrahieren möchten):

hg diff -c xxx --reverse > 1.diff

Angenommen, der aktuelle Tipp ist txxx

hg import 1.diff #creates changeset cxxx1
Hg import 2.diff #creates changeset cxxx2
Hg import 3.diff #creates changeset cxxx3
hg rebase -r cxxx1::cxxx3 -d txxx --collapse
0
Zang XC