Änderungen abbrechen, ohne sie aus dem Verlauf zu löschen

180

Es gibt ein Commit, das einfach nicht funktioniert hat, daher möchte ich es aufgeben, ohne es aus dem Verlauf zu löschen .

Ich habe von einer früheren Revision aktualisiert und mich verpflichtet, wodurch ein neuer Kopf erstellt wurde.


Ich habe keine Zweige, ich möchte keine Zweige, ich möchte einfach mit dem neuen Kopf genau so weitermachen, wie er ist, nichts Besonderes, keine Verschmelzung, keine Sorgen, vergiss einfach den vorherigen.

Ich kann anscheinend nicht herausfinden, wie das geht, und ich fange an zu glauben, dass es nicht geht. Ich finde nur Dinge über Zweige oder Dinge über das Zusammenführen.

o0 '.
quelle
1
Es befindet sich in Ihrem Repo und wurde daher nicht aus dem Verlauf gelöscht. Sie haben einen neuen Kopf erstellt, damit Sie ohne Fehler weitere Überarbeitungen vornehmen können. Was hindert Sie daran, mit dem neuen Kopf weiterzumachen?
Ataylor
Was ist mit Ihrer Abneigung gegen Zweige?
Andres Jaan Tack
@Andres Es ist nicht gerade Abneigung gegen Zweige. Ich brauchte es nur, um ohne einen dummen zusätzlichen Schritt zu arbeiten, nur um es zu schließen.
o0 '.
Jeder, der liest - bitte beachten Sie, dass in diesem Szenario bereits ein Zweig erstellt wurde. Beachten Sie die Erklärung in dieser Antwort: stackoverflow.com/a/3692607/3195477
UuDdLrLrSs

Antworten:

181

Aktualisieren Sie Ihr Repository auf den Kopf mit der Revision, die Sie vergessen möchten, und hg commit --close-branchmarkieren Sie dann diesen (anonymen) Zweig als geschlossen. Aktualisieren Sie dann auf den Leiter des Zweigs, den Sie ausführen wollen, und die Arbeit fortsetzen.

Sie können den geschlossenen Zweig weiterhin sehen, wenn Sie die -cOption verwenden hg heads, aber er wird standardmäßig nicht angezeigt undhg merge nicht weiß, dass Sie nicht versuchen, mit dem geschlossenen Kopf zusammenzuführen.

Sie müssen hg push --forcedas erste Mal verwenden, wenn Sie diesen geschlossenen Kopf in ein anderes Repository verschieben, da Sie beim Push tatsächlich zusätzliche Köpfe im Remote-Repository erstellen. Sagen Sie Mercurial also, dass dies in Ordnung ist --force. Menschen, die am geschlossenen Kopf ziehen, werden von Warnungen nicht gestört.

Niall C.
quelle
3
@Niall C. funktioniert das nicht nur, wenn er das als benannten Zweig markiert hat? Ich gehe davon aus, was er gesagt hat, dass es in der Standardeinstellung ist
msarchet
aber ... das stimmt nicht, ich bekomme immer noch beide Köpfe aufgelistet, wenn ich hg headsanrufe ... Ich verwende mercurial 1.4.3, ist das eine neuere Funktion?
o0 '.
2
@msarchet: AFAIK, versucht es heute, --close-branch funktioniert NICHT für anonyme Zweige. Es sollte, aber nicht. Ich hoffe, dass sich dies in einer zukünftigen Version von Mercurial ändert. Anonyme Zweige sind sehr nett, sollten aber genauso erstklassig sein wie benannte Zweige.
Krazy Glew
4
@KrazyGlew: Das Problem ist, dass ein "anonymer" Zweig wirklich nur ein zweiter Zweig mit demselben Namen ist wie der Zweig, auf dem er basiert. Sie versuchen nicht wirklich, den (benannten) Zweig zu schließen: Sie versuchen, die vorgenommenen Änderungen zu verwerfen. Mit anderen Worten, hg branchessollte immer noch den Filialnamen anzeigen, auf dem Sie sich befinden. Anstatt zu versuchen, den Zweig zu schließen, führen Sie Ihren anonymen Zweig wieder in den ursprünglichen Zweig ein und verwerfen Sie alle Änderungen.
StriplingWarrior
2
In meinem Fall habe ich einen Zweig namens default (dies ist Standard) und einen anderen namens default / master (ich denke aufgrund der Tatsache, dass das Remote-Depot tatsächlich Git ist). hg update default / master; hg commit --close-branch; hg update default hat bei mir funktioniert.
MattD
68

Ich weiß, dass Sie zu diesem Zeitpunkt nicht mit Filialen arbeiten möchten , aber genau das haben Sie getan. Wenn Sie zu einer früheren Version zurückgekehrt sind und etwas festgeschrieben haben, das funktioniert hat, haben Sie einen Zweig erstellt - einen unbenannten Zweig, aber trotzdem einen Zweig.


Es ist kein Problem, einfach so weiterzumachen, wie Sie sind, und sich keine Sorgen um mehrere Köpfe zu machen. Wenn Sie jedoch aufräumen möchten, damit Sie nicht versehentlich einmal den falschen Kopf auswählen, können Sie den alten Ast töten.

In der Mercurial-Dokumentation gibt es einen guten Abschnitt, der Sie durch eine Reihe von Optionen rund um das Beschneiden toter Zweige führt .

Ich denke, die beste Option für Sie ist es, den alten Zweig als "geschlossen" zu markieren. Wenn Ihr alter Kopf Revision "123" ist, dann:

hg update -r 123
hg commit --close-branch -m 'Closing old branch'
hg update -C default
Nick Pierpoint
quelle
3
Blurgh - habe gerade @ Nialls Antwort gesehen, nachdem ich eingetreten war. Will Niall's und meine positiv bewerten, kann im Nullpunktpool schmachten. :)
Nick Pierpoint
1
Ich mag Ihre Antwort besser, es erfordert weniger Groucrials Terminologie (die, soweit ich das beurteilen kann, gewählt zu sein scheint, um Git-Benutzer zu verwirren)
Tacaswell
8
lol es ist das Gegenteil! Die Terminologie von mercurial wurde so gewählt, dass sie für SVN-Benutzer natürlich klingt, während die von Git verdammt verwirrend ist! Wie auch immer, diese Antwort wird positiv bewertet, da sie das letzte Update -C
Tobia vom
2
Warum brauchst du -Cin hg update? Es scheint, dass keine Dateien geändert worden wären, also sollte es ohne sie funktionieren.
Max
1
Soweit ich das beurteilen kann, brauchst du nirgendwo ein -C. Wenn Sie jedoch beim Versuch, ein Update durchzuführen, noch ausstehende Änderungen haben, wird der Vorgang abgebrochen.
Eli Albert
21

Geben Sie zunächst Folgendes ein:

hg heads

Stellen Sie sich vor, Sie haben drei Köpfe aufgelistet:

changeset:   223:d1c3deae6297
user:        Your name  <[email protected]>
date:        Mon Jun 09 02:24:23 2014 +0200
summary:     commit description #3

changeset:   123:91c5402959z3
user:        Your name <[email protected]>
date:        Sat Dec 23 16:05:38 2013 +0200
summary:     commit description #2

changeset:   59:81b9804156a8
user:        Your name <[email protected]>
date:        Sat Sep 14 13:14:40 2013 +0200
summary:     commit description #1

Angenommen, Sie möchten den letzten Kopf aktiv halten (223) und den Rest schließen.

Sie würden dann wie folgt vorgehen:

Kopf Nr. 59 schließen

hg up -r 59
hg ci --close-branch -m "clean up heads; approach abandoned"

Kopf Nr. 123 schließen

hg up -r 123
hg ci --close-branch -m "clean up heads; approach abandoned"

Übernehmen Sie die Änderungen

hg push

Vergessen Sie nicht, am Ende zum rechten Kopf zu wechseln

hg up -r 223

Und du bist fertig.

Artur Barseghyan
quelle
Dies ist ein nettes Tutorial, aber die Beispiel-Commit-Nachrichten sind ein bisschen meta. Ich würde bessere Beispiele hinzufügen, damit diejenigen, die von Ihnen lernen, bessere Commit-Nachrichten liefern können. So etwas wie --close-branch -m "Closing branch - technique #2 abandoned in favor of technique #3".
Jason R. Coombs
5
Außerdem sind Sie am Ende irgendwie fertig, außer dass sich Ihre Arbeitskopie noch auf dem Kopf befindet, den Sie gerade geschlossen haben. Eine weitere Änderung würde am geschlossenen Kopf erfolgen und ihn wieder öffnen. Sie sollten dies tun, hg up -r 223bevor Sie Änderungen vornehmen.
Jason R. Coombs
@ Jason R. Coombs: Richtig!
Artur Barseghyan
Laut @Niall und meiner eigenen Erfahrung müssen Sie hg push --forcenicht nur hg pushdie Warnung über das Drücken mehrerer Köpfe überwinden .
Craq
1
@ Artur Ich stimme im Allgemeinen zu. In diesem Fall hg pushhat es für mich nicht funktioniert. Wie empfehlen Sie, Änderungen an einem externen Repo vorzunehmen, wenn es aufgrund mehrerer Köpfe abgelehnt wird?
craq
12

Sie möchten verwenden hg backout . Dadurch werden die vom Änderungssatz vorgenommenen Änderungen aus jedem untergeordneten Änderungssatz entfernt.

Überprüfen Sie dies für eine gute Erklärung. Mercurial Backout

msarchet
quelle
2
Das ist genau die richtige Antwort. Backout fügt die Umkehrung eines Änderungssatzes hinzu, macht die Arbeit rückgängig und gibt Ihnen eine Commit-Nachricht, um sich daran zu erinnern, warum Ihnen die Idee nicht gefallen hat.
Ry4an Brase
7
Ich bin eigentlich anderer Meinung - die Arbeit auf einem Kopf aufzugeben und von einem guten Ausgangspunkt aus neu zu beginnen, scheint ein saubereres Arbeitsmuster zu sein als die Verwendung von Backouts. Zumal Sie nicht mehr als einen Änderungssatz gleichzeitig zurücksetzen können.
Martin Geisler
1
@ Martin Geisler, nun, ich stimme dem im Allgemeinen zu, aber das OP erklärte, er wolle die Änderungen ohne Verzweigungen aufgeben
msarchet
2
@ Martin Geisler Ja, ich bin alles für die Verzweigung, nur manchmal ist es das Beste, eine schlechte Änderung zu machen
msarchet
1
es mag manchmal nützlich sein, aber das war nicht wirklich das, was ich wollte.
Trotzdem
2

Sowohl Nialls als auch Nicks Antworten sind direkt. Da ich viele baumelnde Köpfe erschaffe, habe ich einen Alias ​​geschrieben, um die Köpfe leichter zu schließen. Indem Sie dies zu Ihrem hinzufügen .hgrc:

[alias]
behead = !REV=$($HG id -i); $HG update $@ -q && $HG ci --close-branch -m "Closing dead head" && $HG update $REV -q

(Wenn Sie bereits einen [alias]Abschnitt haben, können Sie ihn stattdessen anhängen.)

Sie können jetzt einen Kopf in einem einzigen Befehl schließen (und ohne manuell auf einen anderen Änderungssatz aktualisieren zu müssen):

$ hg behead 123

Hinweis: Der Alias ​​nutzt die Tatsache, dass Mercurial-Aliase Shell-Befehle sein können . Dies bedeutet, dass dies wahrscheinlich nur unter UNIX funktioniert, nicht unter Windows.

jjst
quelle
2

Eine Alternative zum Schließen oder Entfernen des unerwünschten Zweigs besteht darin, ihn so zusammenzuführen , dass seine Auswirkungen vollständig verworfen werden, er jedoch in der Geschichte verbleibt. Dieser Ansatz ermöglicht es diesen unerwünschten Änderungen, sich in einem Push zu verbreiten. Verwenden Sie dies also nur, wenn dies der beabsichtigte Effekt ist.

Angenommen, der Änderungssatzverlauf sieht folgendermaßen aus:

1-2-3-4-5-6    
       \    
        7-8-*

und es ist 5und 6welche nicht mehr gewollt sind.

Du kannst das:

hg up 8
hg merge -r 6 -t :local
hg commit ...

was wird dies schaffen:

1-2-3-4-5-6    
       \   \
        7-8-9-*

Das Update 8stellt sicher, dass Sie an der gewünschten Stelle im Verlauf arbeiten, die Sie behalten möchten.

Das -t :localProgramm weist hg an, das Zusammenführungs-Tool " local " zu verwenden, das es anweist , Änderungen aus dem anderen Zweig zu ignorieren, dh dem, der NICHT durch den aktuellen Status des Arbeitsordners dargestellt wird. Mehr Info .

Somit bleiben die unerwünschten Änderungen in 5und 6in der Geschichte erhalten, wirken sich aber nicht auf etwas Neueres aus.

UuDdLrLrSs
quelle
2

Dies ist ein Anwendungsfall für die Evolve-Erweiterung . Es ist derzeit nicht im Lieferumfang von Mercurial enthalten, daher handelt es sich technisch gesehen um eine Erweiterung eines Drittanbieters. Aber es wird ziemlich häufig von einer Reihe von Leuten genutzt, einschließlich Mercurial-Entwicklern, wird sehr aktiv entwickelt und geht nirgendwo hin.

Mit der Evolve-Erweiterung tun Sie dies einfach

hg prune -r revname

und mach weiter mit deinem Leben. Das cset wird noch da sein, aber veraltet. Es ist nur sichtbar, wenn Sie die --hiddenOption an Mercurial-Befehle übergeben, und wird standardmäßig nicht an Remote-Repositorys übertragen. Obwohl ich denke, Sie können es erzwingen, wenn Sie wirklich wollen.

Wenn das Cset, das Sie beschneiden, Vorfahren hat, die Sie behalten möchten, müssen Sie ausgeführt werden, um hg evolvediese Änderungssätze neu zu starten. hg evolvewird dies automatisch tun. Ansonsten müssen Sie nichts tun.

Faheem Mitha
quelle
1

Sie können Ihr beschädigtes Repo auf ein neues klonen, ohne diesen unerwünschten Kopf zu klonen. Entfernen Sie dann das alte Repository, verschieben Sie den neu erstellten Klon an den ursprünglichen Ort und arbeiten Sie weiter damit. Dies wird einige Zeit dauern, aber Sie erhalten ein perfekt sauberes Repository ohne Anzeichen dieser unerwünschten Überarbeitung.

hg clone --rev myGoodResition myDirtyRepo myCleanRepo
kjam
quelle
1
Dies ist absolut nicht das, was ich gefragt habe, sorry.
o0 '.
4
@Kristof: Ist das ein Witz? Lesen Sie die erste Zeile meines Beitrags noch einmal: "Verlassen Sie ihn, ohne ihn aus dem Verlauf zu löschen "
o0 '.
-1

Ich bin oft auf dieses Problem gestoßen, wenn ich einen Kopf enthaupten möchte, der irrtümlich erstellt wurde. Ich möchte immer sehen, wie es vom Erdboden verschwindet.

Holen Sie sich auf Ihrer lokalen Kopie die neueste und dann:

  1. Suchen Sie den Anfang eines Kopfes, den Sie abstreifen möchten (wo sich ein neuer Hals abzweigt), und erhalten Sie die Revisionsnummer

  2. Zieh es aus.


Quelle: TipsAndTricks .

Quelle: PruningDeadBranches # Using_strip .

hg --config extensions.hgext.mq= strip -n <rev>
  1. Nehmen Sie eine einfache Dateiaktualisierung vor (fügen Sie einer Datei ein Leerzeichen hinzu), schreiben Sie sie fest und drücken Sie sie.

Ihr Repo sollte jetzt den Kopf abgestreift haben. Der letzte Schritt ist wichtig, da beim Strippen keine Änderungen vorgenommen werden, die Sie in Ihr zentrales Repository übertragen können. Ohne den letzten Schritt haben Sie den Kopf nur lokal abgestreift.

sonjz
quelle
1
Durch Push wird jedoch niemals etwas aus dem Remote-Repository gelöscht. Es werden immer nur Informationen hinzugefügt . Wenn sich das Änderungsset bereits im zentralen Repository befindet, müssen Sie entweder die Evolve-Erweiterung verwenden oder sie auf dem zentralen Server selbst entfernen. Wenn sich das Änderungsset noch nicht im zentralen Repository befindet, reicht es aus, es lokal zu entfernen, ohne dass ein Push erforderlich ist.
Ben