Kann ich Commits in Mercurial quetschen?


109

Ich habe ein paar Commits, die eigentlich nur eines sein sollten. Wenn ich Git verwenden würde, würde ich verwenden:

git rebase -i <some-commit-before>

und dann zerquetsche sie.

Kann ich das in mercurial machen? Wenn das so ist, wie?

Antworten:


88

Ja, Sie können dies mit mercurial ohne Erweiterungen tun, indem Sie Changesets verketten .

Wenn Sie eine Erweiterung verwenden möchten, können Sie alternativ Folgendes verwenden:


Ja, ich habe diese Antwort aus den betrogenen Fragen heraus gefischt, die ich in meinem Kommentar zur allgemeinen Frage gern hatte. Ich denke, es ist deine Antwort auf diese Frage.
Ry4an Brase

4
Eine kleine Randnotiz: Die Histedit-Erweiterung wird mit Mercurial 2.3 und höher vertrieben. Sie müssen es nur aktivieren.
Paidhi

1
Im Dokument "Verketten von Änderungssätzen" werden abstrakte Konzepte von "Repos" verwendet. Wie verweise ich auf diese? Zum Beispiel: hg -R oldrepo export ... erzeugt "Abbruch: Repository oldrepo nicht gefunden!
Aleksandr Levchuk

13
Ich versuche nur, 2 Commits zu quetschen. Benötige ich wirklich eine Wiki-Seite mit mehr als 10 Befehlen oder alternativen Erweiterungen?
Aleksandr Levchuk

3
Siehe die Kommentare. Histedit ist jetzt integriert, Sie müssen es nur aktivieren (da keine Standardbefehle den Verlauf ändern)
Ry4an Brase

43

Mein Favorit ist hg strip --keepBefehl. Und dann begebe ich alle Änderungen in einem Commit.

Es ist der schnellste und bequemste Weg für mich, weil ich während meiner täglichen Arbeit gerne viele kleine Aufgaben mache;)


Hinweis 1: Zum stripAktivieren ist eine integrierte Erweiterung erforderlich mq.
Hinweis 2: Mein Lieblings-Git / Mercurial-Client (SmartGit / Hg) wird während standardmäßig an einen --keepParameter angehängt strip. Und was noch bequemer ist: Es bietet eine Option namens join commits:]


4
Der vollständige Befehl für hg strip lautet: hg strip --keep --rev [rev] Wo revist die Revisionsnummer des ersten Commits, das Sie mit dem letzten
quetschen

3
@NicolasForney Nicht genau, --revist optional, voller Befehl isthg strip --keep [rev]
G. Demecki

Die Überarbeitung ist für mich in 3.3.3 obligatorisch: hg help stripgibt hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV..., und das Weglassen der Überarbeitung gibt mir abort: empty revision set.
Roman Starkov

3
Verwenden hg stripist nicht die beste Idee. Es ist nicht gerade sicher. Versuchen Sie es hg histedit, vielleicht sogar mit der Evolve-Erweiterung.
Martin Thomson

Scheint der natürlichste Weg für Git-Leute zu sein;)
foo

32

Die Rebase-Erweiterung wirkte wie ein Zauber. So quetschen Sie 2 Commits:

$ hg rebase --dest .~2 --base . --collapse

Punkt ist eine Verknüpfung für die aktuelle Revision.

Es ist noch einfacher, wenn Sie ein paar Commits für einen Zweig haben und sie alle zu einem zusammenfassen möchten:

$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse

So funktioniert das:

Geben Sie hier die Bildbeschreibung ein

(von http://mercurial-scm.org/wiki/RebaseExtension#Collapsing )


1
Wo haben Sie die "~ 2" für zwei Commits gefunden?
Mi-La

1
Es wird im Revsets-Thema erklärt, siehe hg help revsets.
Markand

13

Wenn Sie diese Antwort lesen, können Sie jede andere in dieser Antwort erwähnte Option vergessen und den foldBefehl aus der Evolve-Erweiterung verwenden .

evolveist eine Erweiterung von mercurial, die uns dabei hilft, eine sichere veränderbare Geschichte zu haben. Es ist jedoch immer noch experimentell. Sie können es verwenden, indem Sie es aus dem Repo klonen und wie folgt in Ihre .hgrc-Datei einfügen.

[extensions]
evolve = ~/evolve/hgext/evolve.py

Angenommen, Sie haben das Evolutions-Repo in Ihrem Home-Verzeichnis geklont. Jetzt können Sie loslegen. Sie können auch Hilfe von suchen hg help fold.

Befehl falten

Sie weisen foldan, eine lineare Kette von Commits zu quetschen / zu falten, die nicht unterbrochen ist. Falz erstellt ein neues Änderungsset, das Änderungen aus allen Änderungssätzen enthält, und markiert alle diese Commits als veraltet. Sie können dies unter docs genauer untersuchen .

Angenommen, Sie haben die folgende Geschichte.

a -> b -> c -> d -> e -> f -> g

Sie wollen quetschen e, fund g. Du kannst tun

hg up g
hg fold -r e

Das Ergebnis wird sein

a -> b -> c -> d -> h

Wo hist das Änderungsset, das Änderungen aus allen drei Commits enthält e, fundg .

Sie können auch Änderungssätze aus der Mitte des Verlaufs falten, dh Sie müssen nicht unbedingt eine Kette auswählen, die die Spitze enthält. Angenommen , Sie falten möchten b, cund d. Du kannst tun

hg up d
hg fold -r b
hg evolve --all

Dies führt zu

a -> i -> j

wobei idie gefaltete changeset von b, c, dund jist der gleiche wie changeset h. Evolve Benutzerhandbuch ist ein Muss zu lesen.


Scheint, als würde Rebase die meisten (vielleicht alle?) Anwendungsfälle dieser Erweiterung abdecken, und sicherlich den, der in dieser Frage gestellt wird. Die Killer-Funktion dieser Erweiterung besteht darin, die von Ihnen ersetzten Revisionen auszublenden (anstatt sie zu löschen). Die --keepOption zum erneuten Basieren deckt dies jedoch ab (gefolgt vom Markieren von Revisionen als geheim oder dem Verwenden von Streifen, sobald Sie das Ergebnis überprüft haben). Selbst das Verschieben von Revisionen zwischen anderen Revisionen ist mit einer Folge von zwei Rebase-Befehlen möglich.
Arthur Tacca

... und wenn Sie etwas wirklich Kompliziertes tun, können Sie das lokale Repo immer zuerst klonen, um es als Backup zu verwenden. Wenn man bedenkt, wie selten (hoffentlich!) Das ist, ist es weniger Aufwand als zu lernen, wie man eine völlig neue Erweiterung verwendet.
Arthur Tacca

"NameError: Name 'execfile' ist nicht definiert" - was bedeutet, dass Develop in Python 2 geschrieben ist, was im Grunde die Steinzeit ist.
Neil G

1
@NeilG mercurial unterstützt Python 3 noch nicht.
Pulkit Goyal

2
@NeilG yep, die mercurial community arbeitet hart daran, so schnell wie möglich py3-Unterstützung zu erhalten.
Pulkit Goyal

1

Mit Mercurial 4.8 (November 2018, 9 Jahre später) konnten Sie den neuen Befehl in Betracht ziehen hg absorb(es war zuvor eine experimentelle Funktion ).

Siehe " Absorbieren von Commit-Änderungen in Mercurial 4.8 "

Die absorb-Erweiterung übernimmt jede Änderung in Ihrem Arbeitsverzeichnis, ermittelt, welche Commits in Ihrer Serie diese Zeile geändert haben, und ändert die Änderung automatisch in dieses Commit.
Wenn es Unklarheiten gibt (dh mehrere Commits, die dieselbe Zeile geändert haben), ignoriert absorb diese Änderung einfach und belässt sie in Ihrem Arbeitsverzeichnis, um sie manuell aufzulösen.

hg absorbFindet auf technischer Ebene alle nicht festgeschriebenen Änderungen und versucht, jede geänderte Zeile einem eindeutigen vorherigen Commit zuzuordnen.
Für jede Änderung, die sauber zugeordnet werden kann, werden die nicht festgeschriebenen Änderungen in das entsprechende vorherige Festschreiben übernommen. Von der Operation betroffene Commits werden automatisch neu basiert.
Wenn eine Änderung nicht einem eindeutigen vorherigen Commit zugeordnet werden kann, bleibt sie nicht festgeschrieben, und Benutzer können auf einen vorhandenen Workflow zurückgreifen (z hg histedit. B. mithilfe von ).

Die automatische Umschreibungslogik von hg absorbwird implementiert, indem der Verlauf der Zeilen verfolgt wird: Dies unterscheidet sich grundlegend von dem Ansatz von hg histeditoder git rebase, der sich in der Regel auf Zusammenführungsstrategien stützt , die auf der 3-Wege-Zusammenführung basieren , um eine neue Version einer Datei bei mehrfacher Eingabe abzuleiten Versionen.

Dieser Ansatz kombiniert mit der Tatsache, dass hg absorb Änderungen mit einem mehrdeutigen Anwendungs-Commit überspringt, bedeutet, dass hg absorb niemals auf Zusammenführungskonflikte stößt!

Wenn Sie Zeilen mit mehrdeutigen Anwendungszielen ignorieren, wird der Patch möglicherweise immer sauber angewendet, wenn Sie eine klassische 3-Wege-Zusammenführung verwenden. Diese Aussage klingt logisch richtig. Dies ist jedoch nicht hg absorbder Fall : Kann Zusammenführungskonflikte vermeiden, wenn die Zusammenführung von durchgeführt wird hg histeditoder git rebase -ifehlschlagen würde.


0

Ich denke chistedit(eingebaut seit Mercurial 2.3) ist dem rebase -ireinen Mercurial am nächsten ( chisteditist die interaktive Version von histedit). Sobald der foldBefehl in histedit vorliegt, wird er den Rebases squashund der rollBefehl den Rebases zugeordnet fixup. Siehe histedit Dokumenten.

Hier ist ein einfaches Beispiel. Angenommen, Sie haben Folgendes und möchten alle Änderungen von 1e21c4b1 in die vorherige Revision verschieben und nur die Nachricht der vorherigen Revision beibehalten.

@  1e21c4b1 drees tip
|  A commit you want to squash
o  b4a738a4 drees
|  A commit
o  788aa028 drees
|  Older stuff

Sie können hg chistedit -r b4a738a4den Verlauf zurück zu b4a738a4 bearbeiten. In chistedit bewegen Sie sich dann auf 1e21c4b1 und drücken, rum anzuzeigen, dass Sie diese Revision rollen möchten. Beachten Sie, dass die Reihenfolge in histedit (älteste bis neueste) von hg log(neueste bis älteste) umgekehrt ist .

#0  pick   160:b4a738a49916   A commit
#1  ^roll  161:1e21c4b1500c

Nachdem Sie Ihre Änderungen ausgewählt haben, wählen Sie c legen Sie sie fest. Das Ergebnis ist folgendes:

@ bfa4a3be drees tipp | Ein Commit o 788aa028 drees | Älteres Zeug

Wenn Sie für sie relativ neu sind, histeditkann eine bessere Wahl sein alschistedit weil die Befehlsbeschreibungen in der histedit-Datei als Referenz bereitgestellt werden. Es dauert nur ein bisschen mehr Bearbeitung, um die Befehle mit normaler Textbearbeitung festzulegen (genau wie bei normaler Rebase).

Beachten Sie , verwenden entweder histeditoder chisteditmüssen Sie hinzufügen , histeditum Ihre Erweiterungen in Ihrer ~ / .hgrc:

[extensions]
histedit =

Ich schlug vor, chisteditda es am nächsten ist rebase -iund überall in der Geschichte funktioniert. Wenn Sie wirklich nur die aktuelle Version in die vorherige überarbeiten / optimieren möchten, dann @G. Demeckis stripVorschlag kann gut sein, da klar ist, was passiert. Es ist seit Mercuria 2.8 eingebaut. Um die oben genannten äquivalenten Ergebnisse zu erhalten, können Sie Folgendes tun:

hg strip .
hg add
hg commit --amend

Beachten Sie strip, dass wie bei histedit in Ihrem ~ / .hgrc Folgendes aktiviert sein muss:

[extensions]
strip =

0

Nehmen wir an, Sie möchten 2 der letzten Commits quetschen (vereinen).

  1. Suchen Sie eine Revisionsnummer

    hg log -G -l 3
    

    mögliche Ausgabe:

    @  changeset:   156:a922d923cf6f
    |  branch:      default
    |  tag:         tip
    |  user:        naXa!
    |  date:        Thu Dec 13 15:45:58 2018 +0300
    |  summary:     commit message 3
    |
    o  changeset:   155:5feb73422486
    |  branch:      default
    |  user:        naXa!
    |  date:        Thu Dec 13 15:22:15 2018 +0300
    |  summary:     commit message 2
    |
    o  changeset:   154:2e490482bd75
    |  branch:      default
    ~  user:        naXa!
       date:        Thu Dec 13 03:28:27 2018 +0300
       summary:     commit message 1
    
  2. Soft-Reset-Zweig

    hg strip --keep -r 155
    
  3. Änderungen erneut festschreiben

    hg commit -m "new commit message"
    

Anmerkungen

striperfordert die Aktivierung einer integrierten Erweiterung. Erstellen / Bearbeiten der ~/.hgrcKonfigurationsdatei mit folgendem Inhalt:

[extensions]
strip = 

-1

Ich benutze:

hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
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.