Wie kann ich mit Mercurial eine Reihe von Änderungssätzen vor dem Drücken zu einem komprimieren?


95

Angenommen, ich habe ein lokales und ein entferntes Mercurial-Repository. Jetzt arbeite ich an einer Funktion. Ich arbeite daran und wenn ich denke, dass es fertig ist, lege ich das Änderungsset fest. Wenn ich es ein bisschen mehr teste, finde ich, dass ich diese Funktion weiter verbessern kann, indem ich etwas im Code optimiere. Ich mache die Änderung und verpflichte mich. 20 Minuten später stelle ich fest, dass diese neue Funktion einen Fehler enthält, also behebe ich ihn und begebe ihn auch.

Ich habe jetzt 3 Änderungssätze, die ich wirklich gerne als einen Änderungssatz mit der Meldung "Implementieren von Feature X" an das Remote-Repository senden möchte.

Wie kann ich das ohne großen Aufwand tun? Ich glaube, ich könnte es mit Patches machen, aber es scheint viel Arbeit zu sein.


40
Natürlich ist es nicht meine Aufgabe, Sie davon abzubringen, Ihre Änderungssätze zu komprimieren, aber Sie möchten vielleicht bedenken, dass die Hälfte des Werts der Versionskontrolle Monate und Jahre später auf "Warum" und nicht nur auf "Was" antwortet. Eine genaue Darstellung, wie ein Feature entstanden ist und in welchen Phasen, könnte von zukünftigem Wert sein. Das Verwerfen scheint so ... unkonvertiert.
Ry4an Brase

Dies führt zu einer anderen Frage ... Was ist der Unterschied zwischen "histedit" und "Zusammenbruch"
Sylvanaar

1
Collapse bietet eine Teilmenge der Funktionen von Histedit, und Histedit verfügt über eine viel intuitivere Benutzeroberfläche.
Stefan Rusek

1
Es bietet auch einen Mechanismus zum Bearbeiten der zusammengeführten Änderungssatznachricht.
Stefan Rusek

1
@ Ry4an: Tatsächlich erhöht das Quetschen / Reduzieren in einigen Fällen die Relevanz für die Versionskontrolle. Ohne Squashing hätte ich jeden Tag zwei Commits, die nichts mit Funktionen oder Fehlerkorrekturen zu tun haben, sondern zum Verschieben von Code vom Laptop auf den Desktop und umgekehrt. Sie fügen dem Versionsverlauf nur Rauschen hinzu.
John Reynolds

Antworten:


39

Wie wäre es mit der Collapse Extension ?


20
Grüße aus der Zukunft! Ich habe nur nach der gleichen Funktionalität gegoogelt und anscheinend unterstützt hg dies heutzutage sofort mit hg rebase --collapse. Schauen Sie sich das hg-Wiki mit dem Befehl rebase an. Da diese Frage das dritte Gesamtsuchergebnis und das erste im Stackoverflow ist, dachte ich, dass Informationen nützlich sein könnten.
a.peganz

1
Gruß von noch weiter in der Zukunft !! Die Rebase-Erweiterung scheint ausschließlich darauf ausgerichtet zu sein, Änderungssätze von einem Zweig in einen anderen zu verschieben. Ja, es gibt die Option --collapse, sie scheint jedoch nur dann anwendbar zu sein, wenn eine Reihe von Änderungssätzen über Zweige verschoben wird. Siehe < mercurial-scm.org/wiki/… >
Brad Oestreicher

3
Sie können hg rebasemit --collapseinnerhalb eines einzelnen Zweigs verwenden.
UuDdLrLrSs

52

Die histedit- Erweiterung ist genau das, wonach Sie suchen.

hg histedit -o

oder

hg histedit --outgoing

zeigt eine Liste der ausgehenden Änderungssätze an. Aus der Liste können Sie

  • Falten Sie zwei oder mehr Änderungssätze, um einen einzigen Änderungssatz zu erstellen
  • Löschen Sie Änderungssätze, um sie aus dem Verlauf zu entfernen
  • Ändern Sie die Änderungssätze nach Belieben.

histedit fordert Sie zur Eingabe der neuen Festschreibungsnachricht der gefalteten Änderungssätze auf, die standardmäßig die beiden Nachrichten enthält, wobei "\ n *** \ n" sie trennt.

Sie können ähnliche Ergebnisse auch mit der Erweiterung mq erzielen, dies ist jedoch viel schwieriger.

Sie können die Collapse-Erweiterung auch verwenden, um nur das Falten durchzuführen. Sie bietet jedoch keine so schöne Benutzeroberfläche und keine Möglichkeit, die resultierende Commit-Nachricht zu bearbeiten. Durch das Bearbeiten der resultierenden Festschreibungsnachricht kann auch die endgültige Nachricht bereinigt werden, was ich am Ende immer verwende.


danke, das ist genau das, was ich brauchte. Es wäre schön, wenn Sie dies in TortoiseHg tun könnten - aber die Befehlszeile ist einfach genug.
Sylvanaar

21

Ja, Sie können dies mit Patches tun: Nehmen wir an, Ihre Arbeit befindet sich in den Änderungssätzen 100 bis einschließlich 110

  1. Erstellen Sie einen Patch:

    % hg export -o mypatch 100:110 --git

  2. Update auf 99:

    % hg update 99

  3. Wenden Sie den Patch mit --no-commit an (andernfalls erhalten Sie alle Ihre Änderungssätze zurück):

    % hg import --no-commit mypatch

  4. Übernehmen Sie alle Änderungen auf einmal:

    % hg commit

  5. Sie haben jetzt zwei Köpfe (110 und 111), die in Bezug auf die Dateien, die sie in Ihrem Arbeitsverzeichnis erstellen, gleichwertig sein sollten.

    % hg strip 100

OK, jetzt, wo ich alles dargelegt habe, scheint es langwierig zu sein, aber nachdem ich es ein paar Mal selbst gemacht habe, finde ich es nicht zu mühsam ...


1
Gute Antwort, aber es gibt eine Voraussetzung: Die MQ-Erweiterung muss aktiviert sein .
Chris Kelly

Um auch Änderungen in Binärdateien aufzunehmen, verwenden Sie die Option --git: Beispiel: "hg export -o mypatch 100: 110 --git" Weitere Informationen finden Sie unter: stackoverflow.com/a/12537738/ 367663 Ich habe mir erlaubt , die Antwort zu ändern.
Kharlos Dominguez

1
Scheint überkompliziert, warum nicht hg strip --keepund dann alles in einem einzigen Commit festschreiben?
G. Demecki

@ G.Demecki Weil es eine möglicherweise sehr verlustbehaftete Operation ist ..? Obwohl MQ übertrieben ist (und oft sogar nicht empfohlen wird), außer wenn Sie einen solchen Workflow wünschen.
user2864740

@ user2864740 Sie haben vielleicht Recht, weil ich kein Mercurial-Experte bin. Standardmäßig hg stripwird jedoch ein Backup im .hg/strip-backup/Verzeichnis abgelegt . Ich denke, es ist nicht so sicher git reflog, bietet aber dennoch eine Art Rettung.
G. Demecki

19

Wenn Sie TortoiseHg verwenden, können Sie mit nur zwei Revisionen auswählen (verwenden Sie STRG, um nicht nachfolgende Revisionen auszuwählen), mit der rechten Maustaste klicken und "Verlauf komprimieren" auswählen .

Danach erhalten Sie ab der ersten Änderung, die Sie zuvor ausgewählt haben, eine neue Änderungsliste in neuem Kopf. Sie enthält alle Nachkommen-Änderungslisten zwischen den von Ihnen ausgewählten.

Sie können alte Änderungslisten einfach entfernen, wenn Sie sie nicht mehr benötigen: Verwenden Sie dafür MQ- Erweiterungen. Wiederum in TortoiseHg: Klicken Sie mit der rechten Maustaste auf die erste Änderungsliste, die mit allen Nachkommen entfernt werden muss: "Verlauf ändern -> Entfernen" .


18

Meine bevorzugte Methode zur Verwendung von mq für diese Faltung ist die Verwendung von TortoiseHg, wie hier beschrieben . Dies kann jedoch einfach über die Befehlszeile erfolgen:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

(Es gibt vielleicht einen besseren Weg, um den qfold-Schritt auszuführen, aber ich bin mir dessen nicht bewusst, da ich normalerweise TortoiseHg für diese Operation verwende.)

Es scheint zunächst etwas kompliziert zu sein, aber sobald Sie mit der Verwendung von mq begonnen haben, ist es ziemlich einfach und natürlich - und Sie können mit mq alle möglichen anderen Dinge tun, die ziemlich praktisch sein können!


4

hg collapseund hg histeditsind die besten Wege. Oder besser gesagt, es wäre der beste Weg, wenn sie zuverlässig funktionieren würden ... Ich musste histeditinnerhalb von drei Minuten mit einem Stack-Dump abstürzen.Collapseist nicht viel besser.

Ich dachte, ich könnte zwei andere BKMs teilen:

  1. hg rebase --collapse

    Diese Erweiterung wird mit Mercurial vertrieben. Ich hatte noch keine Probleme damit. Möglicherweise müssen Sie einige Spiele spielen, um hg rebaseEinschränkungen zu umgehen. Grundsätzlich ist es nicht so, dass ein Vorfahr auf demselben Vorfahren mit demselben Namen oder Standard neu erstellt wird, obwohl dies zulässig ist, wenn zwischen (benannten) Zweigen eine Neubasis vorgenommen wird.

  2. Verschieben Sie das Repository ( foo/.hg) in das Arbeitsverzeichnis ( bar) und seine Dateien. Nicht umgekehrt.

Einige Leute haben darüber gesprochen, zwei Klonbäume zu erstellen und Dateien zwischen ihnen zu kopieren. Oder zwischen ihnen flicken. Stattdessen ist es einfacher, die .hgVerzeichnisse zu verschieben.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Dies funktioniert so lange, wie die wahren Repositorys, die .hgBäume, unabhängig vom Arbeitsverzeichnis und seinen Dateien sind.

Wenn sie nicht unabhängig sind ...


Im Jahr 2015 histeditist eine sehr gute Option für diese Aufgabe. Ich vertraue ihm immer noch nicht, da ich eine Git-Rebase -i mache, aber es stürzt nicht ab. Zumindest neuere Versionen lassen Sie auf einem temporären Zweig, wenn etwas schrecklich schief geht, so dass die Änderungssätze das einzige Mal entfernt werden ist, nachdem der neue Zweig festgeschrieben wurde.
user2864740

2

Ich habe Mercurial noch nie benutzt, aber das klingt sehr nach dem, worüber Martin Fowler vor nicht allzu langer Zeit in seinem Blog gesprochen hat:

http://martinfowler.com/bliki/MercurialSquashCommit.html


Das sieht mehr als ein bisschen kompliziert aus, aber danke für den Link. Ehrlich gesagt hoffe ich auf eine magische Erweiterung, die genau das tut, was ich will, wie das Holen und Transplantieren mit Ziehen und Kirschpflücken.
Lucas

0

Warum nicht einfach hg strip --keepbefehlen?

Dann können Sie alle Änderungen als ein Commit festschreiben.


@Strawberry gibt keine Antwort? Es glaubt, es beantwortet perfekt die Frage des Autors. Können Sie Ihren Standpunkt näher erläutern?
G. Demecki

Es ist eine alte Geschichte, also werde ich die Bemerkung zurückziehen - aber die genehmigte Antwort scheint eine maßgeblichere Referenz zu sein.
Erdbeere

1
@ Trawberry In der Tat ist es ein alter Thread. Die akzeptierte Antwort ist jedoch veraltet, da Mercurial für diesen Job keine separate Drittanbieter-Erweiterung mehr benötigt.
G. Demecki

0

HistEdit wird tun, was Sie wollen, aber es ist wahrscheinlich übertrieben. Wenn Sie nur einige Änderungssätze zusammenfalten müssen, erledigt die Collapse Extension die Aufgabe.


1
Es bietet zwar eine viel einfacher zu verwendende und zu verstehende Benutzeroberfläche, was mehr als genug Grund ist, es zu verwenden, aber es bietet auch einen Mechanismus zum Bearbeiten der zusammengeführten Änderungssatznachricht, was eine andere Sache ist, die ich immer tun möchte, wenn ich es tue Änderungssätze zusammenführen.
Stefan Rusek

Und das Problem, nur die Benutzeroberfläche zu verstehen, ist, dass man es wirklich nicht versteht. Wie auch immer, in der Vergangenheit erlaubt histedit das Ändern von "Nachrichten" sowie das Ändern von Nachrichten beim "Falten". Der Histedit ist perfekt; Wenn überhaupt, ist die Kollapserweiterung nicht sinnvoll.
user2864740

0

Angenommen, Sie haben zwei unveröffentlichte Commits THISund THATCommits in Mercurial und möchten, dass sie sich an THISPunkt :: zu einem einzigen Commit verbinden.

... --> THIS --> ... --> THAT --> ... --> LAST

Überprüfen Sie, ob Ihre Commits nicht veröffentlicht wurden ::

$ hg glog -r "draft() & ($THIS | $THAT)"

Update zum LASTFestschreiben ::

$ hg up

und Import Commits bis zu THISin MQ ::

$ hg qimport $THIS::.

Entfernen Sie alle Patches und wenden Sie nur zuerst an THIS::

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Join with THAT::

$ hg qfold $THATNAME

HINWEIS Um den Namen zu finden, THATNAMEverwenden Sie ::

$ hg qseries

Wenden Sie alle Patches an und verschieben Sie sie in den Repository-Verlauf ::

$ hg qpush -a
$ hg qfinish -a

Mein Blog-Beitrag zum Thema ist Beitritt zu zwei Commits in Mercurial .


0

Ja, strip --keepfunktioniert für die Frage des Autors. Aber es war etwas anders als bei anderen, zum Beispiel, wenn Sie eine Version von 1 bis 30 haben, aber nur die Version 12-15 reduzieren möchten. Andere Lösungen funktionieren aber nicht strip --keep.

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.