Mercurial: jak zmienić ostatnie zatwierdzenie?


211

Szukam odpowiednika git commit --amendw Mercurial, tj. Sposobu modyfikacji zatwierdzenia, z którym jest połączona moja kopia robocza. Interesuje mnie tylko ostatnie zatwierdzenie, a nie arbitralne wcześniejsze zatwierdzenie.

Wymagania dotyczące tej procedury zmiany są następujące:

  • jeśli to możliwe, nie powinno wymagać żadnych rozszerzeń. Nie może wymagać rozszerzeń innych niż domyślne , tzn. Rozszerzeń, które nie są dostarczane z oficjalną instalacją Mercurial.

  • jeśli zobowiązanie do zmiany jest jednym szefem mojego obecnego oddziału, nie należy tworzyć nowego szefa . Jeśli zatwierdzenie nie jest nagłówkiem, może zostać utworzony nowy nagłówek.

  • procedura powinna być bezpieczna w taki sposób, że jeśli z jakichkolwiek przyczyn zmiana się nie powiedzie, chcę przywrócić tę samą kopię roboczą i stan repozytorium jak przed zmianą. Innymi słowy, jeśli sama poprawka może się nie powieść, powinna istnieć bezpieczna procedura przywracania kopii roboczej i stanu repozytorium. Mam na myśli „awarie”, które leżą w naturze procedury zmiany (jak np. Konflikty), a nie problemy związane z systemem plików (takie jak ograniczenia dostępu, niemożność zablokowania pliku do zapisu, ... )

Aktualizacja (1):

  • procedura musi być zautomatyzowana , aby mogła być wykonywana przez klienta GUI bez wymaganej interakcji użytkownika.

Aktualizacja (2):

  • pliki w katalogu roboczym nie mogą być dotykane (niektóre zmodyfikowane pliki mogą blokować system plików). Oznacza to w szczególności, że możliwe podejście w żadnym momencie nie może wymagać czystego katalogu roboczego.

Odpowiedzi:


289

Wraz z wydaniem Mercurial 2.2 możesz użyć --amendopcji z, hg commitaby zaktualizować ostatnie zatwierdzenie w bieżącym katalogu roboczym

Z odwołania do wiersza poleceń :

Flagi --amend można użyć do zmiany elementu nadrzędnego katalogu roboczego za pomocą nowego zatwierdzenia, który zawiera zmiany w elemencie nadrzędnym oprócz zmian aktualnie zgłaszanych przez status hg, jeśli takie istnieją. Stare zatwierdzenie jest przechowywane w pakiecie kopii zapasowych w .hg / strip-backup (zobacz pakiet pomocy hg i pomoc hg na temat rozpakowywania).

Wiadomość, użytkownik i data są pobierane ze zmienionego zatwierdzenia, chyba że określono inaczej. Gdy wiadomość nie zostanie podana w wierszu poleceń, edytor otworzy się z komunikatem o zmienionym zatwierdzeniu.

Wspaniałą rzeczą jest to, że ten mechanizm jest „bezpieczny”, ponieważ opiera się na stosunkowo nowej funkcji „Fazy”, aby zapobiec aktualizacjom, które zmieniłyby historię, która została już udostępniona poza lokalnym repozytorium.


2
Dobra odpowiedź! Eksperymentalne rozszerzenie evolve pozwala bezpiecznie modyfikować zatwierdzenia inne niż główne . Stare zatwierdzenie zostanie oznaczone jako przestarzałe i ukryte. Dzięki serwerowi niepublikowanemu możesz to zrobić nawet po wypchnięciu zestawów zmian.
Martin Geisler

5
Aby po prostu zaktualizować wiadomość przy ostatnim zatwierdzeniu: hg commit --amend -m „to jest moja nowa wiadomość”
Jay Sheth

52

Masz 3 opcje edycji zatwierdzeń w Mercurial:

  1. hg strip --keep --rev -1cofnij ostatnie (1) zatwierdzenie (s), abyś mógł to zrobić ponownie ( więcej informacji znajdziesz w tej odpowiedzi ).

  2. Korzystanie z rozszerzenia MQ , które jest dostarczane z Mercurial

  3. Nawet jeśli nie jest dostarczany z Mercurialem, warto wspomnieć o rozszerzeniu Histedit

Możesz także zajrzeć na stronę Historia edycji wiki Mercurial.

Krótko mówiąc, edycja historii jest naprawdę trudna i odradzana . A jeśli już wprowadziłeś zmiany, prawie nic nie możesz zrobić, z wyjątkiem sytuacji, gdy masz całkowitą kontrolę nad wszystkimi innymi klonami.

Nie znam się tak naprawdę na git commit --amendpoleceniu, ale AFAIK, Histedit wydaje się być najbliższym podejściem, ale niestety nie jest dostarczane z Mercurialem. Korzystanie z MQ jest naprawdę skomplikowane, ale możesz z nim zrobić prawie wszystko.


1
Nie jestem pewien, dlaczego przegapiłem wycofywanie, ale wydaje się, że robi (prawie) to, czego chcę. Jedynym problemem jest to, że gdy plik został usunięty dla mojego pierwotnego zatwierdzenia i został wskrzeszony dla mojego zmienionego zatwierdzenia: przed wycofaniem zostanie cofnięty, po wycofaniu zostanie zaplanowany do usunięcia (ale plik nadal istnieje w katalog roboczy)
mstrap

@Marc Nie jestem pewien, czy rozumiem twój problem, ale spójrz na polecenie zapomnienia, myślę, że to jest to, czego szukasz.
krtek

Nie sądzę, żeby „zapomnienie” było tu pomocne. Oto problem bardziej szczegółowo: (1) Jestem w wersji 2 (2) Usuń „plik” i wprowadzę kilka innych zmian (3) Zatwierdź zmiany, w wyniku czego pojawi się wersja 3 (4) Teraz zmienię zdanie i zdecyduję „plik” nie powinien być usuwany z zatwierdzenia, dlatego chcę zmienić wersję 3. Dlatego dodam ponownie „plik”, który jest teraz niewersjonowany (5) Teraz wykonuję wycofywanie: spowoduje zresetowanie dirstate i oznaczenie „ plik ”po usunięciu. (6) Gdy ponownie wykonasz polecenie „hg commit”, „plik” pozostanie jako usunięty, chociaż nie powinien już być. Jak może wyglądać zautomatyzowana naprawa tego?
mstrap

1
W przypadku części zautomatyzowanej nie wiem, ale możesz hg revert myfilecofnąć usunięcie. Być może ponowne dodanie hg adddo pliku po rollbackrównież działa.
krtek

3
Zgadzam się, że należy unikać edytowania historii opublikowanych zmian, ale edytowanie mojej lokalnej historii jest jedną z głównych atrakcji DVCS. MQ ze swoim qimportem to edycja AFAICT.
mstrap

38

Odpowiednik GUI dla hg commit --amend:

Działa to również z GUI TortoiseHG (używam wersji 2.5):

Przejdź do widoku „Zatwierdź” lub w widoku stołu roboczego wybierz pozycję „katalogu roboczego”. Przycisk „Zatwierdź” ma opcję „Zmień bieżącą wersję” (kliknij strzałkę przycisku, aby ją znaleźć).

wprowadź opis zdjęcia tutaj

          ||
          ||
          \/

wprowadź opis zdjęcia tutaj

Zastrzegający emptor :

Ta dodatkowa opcja zostanie włączona tylko wtedy, gdy wersja rtęciowa to co najmniej 2.2.0, a jeśli bieżąca wersja nie jest publiczna, nie jest łatką i nie ma potomków. [...]

Kliknięcie przycisku wywoła polecenie „commit --amend”, aby „zmienić” poprawkę.

Więcej informacji na ten temat na kanale deweloperskim THG


Bardzo pomocny, dzięki. THG jest wystarczająco sprytny, aby domyślnie wyświetlić komunikat zatwierdzenia (zmiany) w komunikacie z poprzedniego zatwierdzenia - dokładnie tego, czego chciałem.
UuDdLrLrSs 12.10.16

7

Dostrajam się do tego, co napisał Krtek. W szczególności rozwiązanie 1:

Założenia:

  • popełniłeś jeden (!) zestaw zmian, ale jeszcze go nie wypchnąłeś
  • chcesz zmodyfikować ten zestaw zmian (np. dodać, usunąć lub zmienić pliki i / lub komunikat zatwierdzenia)

Rozwiązanie:

  • służy hg rollbackdo cofnięcia ostatniego zatwierdzenia
  • zatwierdzić ponownie, wprowadzając nowe zmiany

Wycofanie naprawdę cofa ostatnią operację. Jego sposób działania jest dość prosty: normalne operacje w HG będą dołączane tylko do plików; obejmuje to zatwierdzenie. Mercurial śledzi długości plików ostatniej transakcji, a zatem może całkowicie cofnąć się o jeden krok, skracając pliki z powrotem do ich starych długości.


1
Dzięki za rozwiązanie tuningowe (1); z przywracaniem został tylko mały problem, proszę zobaczyć mój komentarz dotyczący rozwiązania krtek.
mstrap

8
Jedną z rzeczy, na które należy zwrócić uwagę przy wycofywaniu, ponieważ łapie ludzi, jest to, że jest to ostatnia transakcja repo, która jest wycofywana, a nie ostatnie zatwierdzenie. Więc jeśli coś innego spowodowało zapis do repozytorium, wycofanie nie pomoże. Jest to subtelna, ale ważna rzecz do zapamiętania. MQ i histedit mogą pomóc po zamknięciu okna wycofywania, ale nadal tylko do pewnego momentu.
Paul S

7

Zakładając, że nie rozpowszechniłeś jeszcze swoich zmian, oto, co możesz zrobić.

  • Dodaj do swojego .hgrc:

    [extensions]
    mq =
    
  • W twoim repozytorium:

    hg qimport -r0:tip
    hg qpop -a
    

    Oczywiście nie musisz zaczynać od zera zero lub usunąć wszystkie łatki, ponieważ wystarczy tylko jeden ostatni pop ( hg qpop) (patrz poniżej).

  • usuń ostatni wpis w .hg/patches/seriespliku lub łatki, których nie lubisz. Możliwa jest również zmiana kolejności.

  • hg qpush -a; hg qfinish -a
  • usuń .diffpliki (niezastosowane łatki) nadal znajdujące się w .hg / łatkach (powinno być w twoim przypadku).

Jeśli nie chcesz , aby wziąć z powrotem wszystko z plastra, można edytować go za pomocą hg qimport -r0:tip(lub podobne), a następnie edytuj rzeczy i wykorzystanie hg qrefreshdo scalić zmiany do najwyższego plaster na stosie. Czytać hg help qrefresh.

Poprzez edycję .hg/patches/seriesmożesz nawet usunąć kilka łatek lub zmienić ich kolejność. Jeśli ostatnia wersja to 99, możesz po prostu użyć hg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a.

Oczywiście ta procedura jest wysoce odradzana i ryzykowna . Zrób kopię zapasową wszystkiego, zanim to zrobisz!

Na marginesie zrobiłem to zilliony razy na repozytoriach prywatnych.


Zastanawiałem się również nad użyciem rozszerzenia mq, jednak wymaga to dość wielu operacji, w przypadku których niektóre z nich mogą się nie powieść (np. Jeśli w grę wchodzą pliki binarne). Co więcej, edytowanie plików .hg / patch / series jest niedopuszczalne, ponieważ ta procedura powinna być używana w kliencie GUI (zaktualizowałem wymagania powyżej)
mstrap

Hmmm, przepraszam, że to nie będzie dla ciebie, w prywatnym repozytorium to naprawdę kopie tyłek (z kopiami zapasowymi - już z tobą zniszczyłem repozytorium ^^). Całkiem fajnie jest łączyć łatki w jedną przed wprowadzeniem lokalnych zmian za pomocą hg qfold, btw
hochl

+1 za używanie MQ, ale myślę, że przesadziłeś. Pyta tylko o zmianę ostatniego zatwierdzenia. Również ten import przekręci się, gdy tylko dojdzie do scalenia. „qimport -r tip; <edycja rzeczy>; qrefresh -e; qfin -a 'wykona zadanie (-e, aby edytować komunikat zatwierdzenia)
Paul S

prawda, scalenia są problemem, zwykle używam tylko jednej łatki i używam hg import -r<prev>:tip. Szkoda, że ​​nie ma skrótu do poprzedniej wersji, jak w Subversion.
hochl

2

Najnowsze wersje Mercurial zawierają evolverozszerzenie, które udostępnia hg amendpolecenie. Pozwala to na zmianę zatwierdzenia bez utraty historii zmian wstępnych w kontroli wersji.

hg zmień [OPCJA] ... [PLIK] ...

aliasy: odśwież

połącz zestaw zmian z aktualizacjami i zastąp go nowym

Commits a new changeset incorporating both the changes to the given files
and all the changes from the current parent changeset into the repository.

See 'hg commit' for details about committing changes.

If you don't specify -m, the parent's message will be reused.

Behind the scenes, Mercurial first commits the update as a regular child
of the current parent. Then it creates a new commit on the parent's
parents with the updated contents. Then it changes the working copy parent
to this new combined changeset. Finally, the old changeset and its update
are hidden from 'hg log' (unless you use --hidden with log).

Zobacz https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve, aby uzyskać pełny opis evolverozszerzenia.


Ponowne użycie tego samego komunikatu zatwierdzenia jest fajną funkcją!
mpen

1

Może nie rozwiąże wszystkich problemów w pierwotnym pytaniu, ale ponieważ wydaje się to de facto postem na temat tego, jak mercurial może zmienić poprzednie zatwierdzenie, dodam informacje o wartości 2 centów.

Jeśli jesteś podobny do mnie i chcesz tylko zmodyfikować poprzednią wiadomość zatwierdzenia (naprawić literówkę itp.) Bez dodawania żadnych plików, to zadziała

hg commit -X 'glob:**' --amend

Bez żadnych wzorców dołączania lub wykluczania hg commitdomyślnie uwzględniają wszystkie pliki w katalogu roboczym. Stosowanie wzoru-X 'glob:**' wyklucza wszystkie możliwe pliki, pozwalając jedynie na modyfikację komunikatu zatwierdzenia.

Funkcjonalnie jest tak samo, jak w git commit --amendprzypadku braku plików w indeksie / etapie.


0

Innym rozwiązaniem może być uncommitpolecenie, aby wykluczyć określony plik z bieżącego zatwierdzenia.

hg uncommit [file/directory]

Jest to bardzo pomocne, gdy chcesz zachować bieżące zatwierdzenie i files/directoriesusunąć zaznaczenie niektórych plików z zatwierdzenia (szczególnie pomocne w przypadku ich usunięcia).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.