Frage an mercurial, rollback – Wie wende ich in mercurial einen Reverse-Patch auf eine bestimmte Datei an?

19

BezüglichMercurial: Zusammenführen einer Datei zwischen Zweigen in einem Repo Ich versuche, einen Backout-Vorgang für eine einzelne Datei durchzuführen, obwohl diese Datei einer von vielen Teilnehmern an der Zurücksetzung der Revision war.

Da HG das am Änderungssatz orientierte Tool ist, möchte es nicht mit Dateien arbeiten.

Als nächstes konnte ich feststellen, dass ich hg export verwenden musste, um ein Diff zu erstellen, das Diff manuell zu bearbeiten und dann hg importieren musste, um die Datei in umgekehrter Reihenfolge zu patchen.

..aber dann traf ich diese nervige Situation wohttp://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html behauptet, dass es eine --reverse Option gibthg patch wenn es nicht gibt.

Das Nächste, was ich mir vorstellen kann, ist, einen handbearbeiteten Patch wie oben zu generieren und dann mit Vanille-Patch -R einen Reverse-Patch anzuwenden.

Dashg backout Befehl scheint hier nützlich zu sein, ist aber eigentlich ein roter Hering.

Es muss einen besseren Weg geben, nein?

Die --reverse Option ist zuPatchnichthg patch. balpha

Deine Antwort

3   die antwort
22

Sie können es nur mit der-I (Fügen Sie Namen hinzu, die mit den angegebenen Mustern übereinstimmen) Argument für Zurücksetzen mit einer einzelnen Zeile:

hg backout --merge -I thefiletorevert -m 'message' OFFENDINGREVISIONID

Beispielskript:

hg init testrepo
cd testrepo
echo -e "line1\n\nline3" > file1
echo -e "line1\n\nline3" > file2
hg commit -A -m 'changes to two files'
perl -pi -e 's/line1/line 1/' file1
perl -pi -e 's/line1/line 1/' file2
hg commit -m 'put spaces in line1'
perl -pi -e 's/line3/line 3/' file1
perl -pi -e 's/line3/line 3/' file2
hg commit -m 'put spaces in line3'
hg backout --merge -I file1 -m 'remove spaces from line1' 1

Beispielausgabe:

adding file1
adding file2
reverting file1
created new head
changeset 3:6d354f1ad4c5 backs out changeset 1:906bbeaca6a3
merging with changeset 3:6d354f1ad4c5
merging file1
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Resultierender Dateiinhalt:

file1:line1
file1:line 3
file2:line 1
file2:line 3

Beachten Sie, dass Datei1 nach dem Backout des mittleren Changesets keinen Platz in Zeile 1 hat und das ausführliche Protokoll nur eine Datei anzeigt, die im Backout geändert wurde:

$ hg log -v -r tip
changeset:   3:6d354f1ad4c5
tag:         tip
parent:      1:906bbeaca6a3
user:        Ry4an Brase <[email protected]>
date:        Mon Sep 14 12:17:23 2009 -0500
files:       file1
description:
remove spaces from line1
Cool. Wenn Sie ein Beispiel mit dem Zurücksetzen einer vergrabenen Änderung posten würden, würde ich es als richtig markieren. djsadinoff
Zurücksetzen des mittleren Änderungssatzes Ry4an Brase
Naja, dies würde gut für ein nicht-tip-Änderungsset funktionieren, obwohl Sie am Ende 'hg merge' müssen. Sie würden jedoch immer noch ein Verlaufsdiagramm erhalten, das genau wiedergibt, was passiert ist und die Herkunft ändert, im Gegensatz zu Balphas Copy-it-Over, das ein lineares Changelog ergeben würde. Ry4an Brase
Ich glaube, ich verstehe diese Lösung, aber dieser Fall scheint einfacher zu sein als der meine, da Sie hier die Tippänderung zurücksetzen (eine der Dateien darin), während sich balpha mit meinem allgemeineren Fall des Zurücksetzens einer historischen Änderung befasst. djsadinoff
6

Verwenden Sie einen neuen Klon der tip-Revision.

hg backout --merge -r revision_where_the_change_happened

um die rückgängig gemachten Änderungen in die Arbeitskopie einzufügen.

Kopieren Sie nun die betreffende Datei in Ihre reguläre Arbeitskopie und bestätigen Sie

hg commit -m "Reversed the changes to file.h made in revision bla"

und wirf den oben erstellten Klon weg.

Auf diese Weise weiß mercurial nicht, dass es eine Verbindung zwischen gibtrevision_where_the_change_happened und diese verpflichten. Wenn Sie möchten, dass sich mercurial daran erinnert, machen Sie stattdessen a

hg revert {all files except the one in question}

Nach dem Zusammenführen des Backouts in die Arbeitskopie und vor dem Festschreiben. Zum zweiten müssen Sie nicht an einem Klon arbeiten, da Sie das Backout-Commit beibehalten möchten.

Ich würde vermuten, dass die Wahl, welche Art und Weise Sie verwenden, davon abhängt, wie groß ein Teil des Änderungssatzes der bestimmten Dateiänderung war.

3

Verwenden Sie den Befehl revert.

hg revert -r1 file

Dadurch sollte der Inhalt der Datei auf die Version in Revision 1 zurückgesetzt werden. Anschließend können Sie sie weiter bearbeiten und wie gewohnt festschreiben.

Es ist richtig, dass Sie eine Datei auf eine frühere Version zurücksetzen können. Es würde sogar hier funktionieren, wenn die Datei seit der schlechten Version nicht geändert wurde. Wenn jedoch weitere Änderungen vorgenommen wurden, funktioniert ein einfacher Zurücksetzen nicht. Stattdessen müssten Sie auf die fehlerhafte Revision aktualisieren, die Datei auf eine gute Version zurücksetzen, ein Commit ausführen und die beiden Köpfe zusammenführen. Ich glaube, das ist im Grunde das, was Backout für Sie tut. Martin Geisler

Verwandte Fragen