Czy mogę zgniatać commity w Mercurial?


109

Mam parę zatwierdzeń, które naprawdę powinny być tylko jednym. Gdybym używał gita, użyłbym:

git rebase -i <some-commit-before>

a następnie zgnieć je.

Czy mogę to zrobić w Mercurial? Jeśli tak to jak?

Odpowiedzi:


88

Tak, możesz to zrobić, używając Mercurial bez żadnych rozszerzeń, łącząc zestawy zmian .

Alternatywnie, jeśli chcesz użyć rozszerzenia, możesz użyć:


Tak, wyłowiłem tę odpowiedź z fałszywych pytań, które lubiłem w komentarzu do pytania ogólnego. Myślę, że to twoja odpowiedź.
Ry4an Brase

4
Mała uwaga na marginesie: rozszerzenie Histedit jest dystrybuowane z Mercurial 2.3 i nowszymi wersjami. Musisz tylko to włączyć.
Paidhi

1
W dokumencie Concatenating Changesets używa się abstrakcyjnych pojęć „repozytoriów”, jak mam się do nich odnieść? Na przykład: hg -R oldrepo export ... produkuje "abort: repository oldrepo not found!
Aleksandr Levchuk

13
Po prostu próbuję zgnieść 2 zatwierdzenia. Czy naprawdę potrzebuję strony wiki z ponad 10 poleceniami lub alternatywnymi rozszerzeniami?
Aleksandr Levchuk

3
Zobacz komentarze. Histedit jest teraz wbudowany, wystarczy go włączyć (ponieważ żadne domyślne polecenia nie modyfikują historii)
Ry4an Brase

43

Moim ulubionym jest hg strip --keeprozkaz. A potem zatwierdzam wszystkie zmiany w jednym zatwierdzeniu.

To dla mnie najszybszy i najwygodniejszy sposób, bo w codziennej pracy lubię wykonywać wiele drobnych zleceń;)


Uwaga 1: do włączenia strippotrzebne jest wbudowane rozszerzenie mq.
Uwaga 2: Mój ulubiony klient Git / Mercurial (SmartGit / Hg) domyślnie dodaje --keepparametr podczas strip. A co jest jeszcze wygodniejsze: udostępnia opcję o nazwie join commits:]


4
Pełne polecenie dla paska hg to: hg strip --keep --rev [rev] Gdzie revjest numer wersji pierwszego zatwierdzenia, które chcesz zgnieść z ostatnim
Nicolas Forney

3
@NicolasForney Niezupełnie, --revjest opcjonalne, pełne polecenie tohg strip --keep [rev]
G. Demecki

Rewizja jest obowiązkowa dla mnie w 3.3.3: hg help stripdaje hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV..., a pomijając korektę daje mi abort: empty revision set.
Roman Starkov

3
Używanie hg stripnie jest najlepszym pomysłem. To nie jest do końca bezpieczne. Spróbuj hg histedit, a może nawet spróbuj użyć rozszerzenia evolve.
Martin Thomson,

Wydaje się najbardziej naturalny sposób dla gitów;)
foo

32

Przedłużenie rebase pracował jak czar. Aby zmiażdżyć 2 zatwierdzenia:

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

Kropka to skrót do aktualnej wersji.

Jest to jeszcze łatwiejsze, gdy masz kilka zatwierdzeń na gałęzi i chcesz je wszystkie zwinąć w jedną:

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

Jak to działa:

wprowadź opis obrazu tutaj

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


1
Gdzie znalazłeś „~ 2” dla dwóch zatwierdzeń?
Mi-La

1
Jest to wyjaśnione w temacie revsets, zobacz hg help revsets.
markand

13

Jeśli czytasz tę odpowiedź, możesz zapomnieć o każdej innej opcji wymienionej w tej odpowiedzi i użyć foldpolecenia z rozszerzenia evolve .

evolvejest rozszerzeniem mercurial, które pomaga nam w bezpiecznej mutowalnej historii, ale wciąż jest eksperymentalne. Możesz go użyć, klonując go z repozytorium i dodając do swojego .hgrc w ten sposób.

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

Zakładając, że sklonowałeś repozytorium evolve w swoim katalogu domowym. Teraz możesz już iść. Możesz również szukać pomocy przez hg help fold.

Polecenie zwijania

Mówisz, foldaby zgnieść / złożyć liniowy łańcuch zatwierdzeń, który nie jest zepsuty. To, co robi fold, to tworzy nowy zestaw zmian, który zawiera zmiany ze wszystkich zestawów zmian i oznacza wszystkie te zatwierdzenia jako przestarzałe. Możesz uzyskać dokładniejszy wgląd w to w docs .

Teraz załóżmy, że masz następującą historię.

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

Chcesz się zgnieść e, fi g. Możesz to zrobić

hg up g
hg fold -r e

Wynik będzie

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

gdzie hjest zbiorem zmian, który zawiera zmiany ze wszystkich trzech zatwierdzeń e, fa g.

Możesz również składać zestawy zmian z połowy historii, tzn. Niekoniecznie musisz wybierać łańcuch, który zawiera końcówkę. Załóżmy, że chcemy złożyć b, ci d. Możesz to zrobić

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

Spowoduje to

a -> i -> j

gdzie ijest złożona changeset o b, c, di jjest taka sama, jak changeset h. Podręcznik użytkownika Evolve to lektura obowiązkowa.


Wygląda na to, że rebase obejmuje większość (może wszystkie?) Przypadki użycia tego rozszerzenia, a na pewno ten, o który pytamy w tym pytaniu. Zabójczą funkcją tego rozszerzenia jest ukrywanie (zamiast usuwania) wersji, które zastępujesz, ale --keepopcja rebase to obejmuje (po czym następuje oznaczenie wersji jako tajne lub użycie paska po sprawdzeniu wyniku). Możliwe jest nawet przenoszenie wersji między innymi wersjami za pomocą sekwencji dwóch poleceń zmiany bazy.
Arthur Tacca,

... dodatkowo, jeśli robisz coś naprawdę skomplikowanego, zawsze możesz najpierw sklonować lokalne repozytorium, aby użyć go jako kopii zapasowej. Biorąc pod uwagę to, jak rzadko (miejmy nadzieję!) To mniej wysiłku niż nauka korzystania z zupełnie nowego rozszerzenia.
Arthur Tacca,

„NameError: name 'execfile' nie jest zdefiniowana” - co oznacza, że ​​evolve jest napisane w Pythonie 2, który jest w zasadzie epoką kamienia łupanego.
Neil G

1
@NeilG mercurial nie obsługuje jeszcze Pythona 3.
Pulkit Goyal

2
@NeilG Tak, społeczność Mercurial ciężko pracuje, aby jak najszybciej uzyskać wsparcie dla py3.
Pulkit Goyal

1

W przypadku Mercurial 4.8 (listopad 2018, 9 lat później) można było rozważyć nowe polecenie hg absorb(wcześniej była to funkcja eksperymentalna ).

Zobacz „ Absorpcja zmian dotyczących zobowiązań w Mercurial 4.8

Rozszerzenie absorb zajmie każdą zmianę w twoim katalogu roboczym, określi, które zmiany w twojej serii zmodyfikowały tę linię i automatycznie poprawi zmianę w tym zatwierdzeniu.
Jeśli jest jakaś niejasność (np. Wiele zatwierdzeń zmodyfikowanych w tej samej linii), absorb po prostu zignoruje tę zmianę i pozostawi ją w katalogu roboczym, aby rozwiązać ją ręcznie.

Na poziomie technicznym hg absorbwyszukuje wszystkie niezatwierdzone zmiany i próbuje odwzorować każdą zmienioną linię na jednoznaczne wcześniejsze zatwierdzenie.
Dla każdej zmiany, którą można dokładnie odwzorować, niezatwierdzone zmiany są wchłaniane do odpowiedniego wcześniejszego zatwierdzenia. Zatwierdzenia, na które ma wpływ operacja, są automatycznie zmieniane.
Jeśli zmiana nie może być odwzorowana na jednoznaczne wcześniejsze zatwierdzenie, pozostaje niezatwierdzona, a użytkownicy mogą wrócić do istniejącego przepływu pracy (np. Używając hg histedit).

Logika automatycznego przepisywania hg absorbjest realizowana przez śledzenie historii wierszy: Jest to zasadniczo różne od podejścia przyjętego przez hg histeditlub git rebase, które zwykle polegają na strategiach scalania opartych na łączeniu 3-kierunkowym w celu uzyskania nowej wersji pliku z wieloma danymi wejściowymi wersje.

To podejście w połączeniu z faktem, że hg absorb pomija zmiany z niejednoznacznym zatwierdzeniem aplikacji, oznacza, że ​​hg absorb nigdy nie napotka konfliktów scalania!

Teraz możesz pomyśleć, że jeśli zignorujesz linie z niejednoznacznymi celami aplikacji, łatka zawsze zostanie zastosowana czysto przy użyciu klasycznego scalania trójdrożnego. To stwierdzenie logicznie brzmi poprawnie. Ale tak nie jest: hg absorbmożna uniknąć konfliktów scalania, gdy scalanie wykonane przez hg histeditlub git rebase -izakończy się niepowodzeniem.


0

Myślę, że chistedit(wbudowany od wersji Mercurial 2.3) jest najbliższy rebase -itemu czysty Mercurial ( chisteditjest to interaktywna wersja histedit). Kiedy już się pojawiło, foldpolecenie mapuje do rebase, squasha rollmapy poleceń do rebase fixup. Aby uzyskać więcej informacji, zobacz dokumentację histedit .

Oto prosty przykład. Załóżmy, że masz następujące elementy i chcesz przenieść wszystkie zmiany 1e21c4b1 do poprzedniej wersji, zachowując po prostu komunikat z poprzedniej wersji.

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

Możesz uruchomić hg chistedit -r b4a738a4edycję historii z powrotem do b4a738a4. W chistedit następnie przesuń kursor w dół do 1e21c4b1 i naciśnij, raby wskazać, że chcesz rzucić tę wersję. Zwróć uwagę, że kolejność w histedit (od najstarszych do najnowszych) jest odwrócona z hg log( od najnowszych do najstarszych).

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

Po wybraniu zmian decydujesz csię je zatwierdzić. Wynik jest następujący:

@ bfa4a3be drees tip | Zatwierdzenie 788aa028 drees | Starsze rzeczy

Jeśli jesteś dla nich stosunkowo nowy, histeditmoże to być lepszy wybór niż chisteditdlatego, że zawiera opisy poleceń w pliku histedit w celach informacyjnych. Po prostu wymaga trochę więcej edycji, aby ustawić polecenia za pomocą normalnej edycji tekstu (tak jak normalna rebase).

Uwaga, aby użyć któregoś z nich histeditlub chisteditmusisz dodać histeditdo swoich rozszerzeń w swoim ~ / .hgrc:

[extensions]
histedit =

Zasugerowałem, chisteditponieważ jest najbliżej rebase -ii działa w dowolnym miejscu w historii. Jeśli naprawdę chcesz po prostu podciągnąć / dostosować bieżącą wersję do poprzedniej, @G. Sugestia Demeckiego stripmoże być dobra, ponieważ to, co się dzieje, jest jasne. Jest wbudowany od wersji Mercuria 2.8. Aby uzyskać równoważne wyniki jak powyżej, możesz wykonać następujące czynności:

hg strip .
hg add
hg commit --amend

Uwaga strip, podobnie jak histedit, musi być włączone w twoim ~ / .hgrc:

[extensions]
strip =

0

Załóżmy, że chcesz zgnieść (zjednoczyć) 2 ostatnie zatwierdzenia.

  1. Znajdź numer wersji

    hg log -G -l 3
    

    możliwe wyjście:

    @  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. Gałąź z miękkim resetem

    hg strip --keep -r 155
    
  3. Zatwierdź zmiany ponownie

    hg commit -m "new commit message"
    

Uwagi

stripwymaga włączenia wbudowanego rozszerzenia. Utwórz / edytuj ~/.hgrcplik konfiguracyjny z następującą zawartością:

[extensions]
strip = 

-1

Używam:

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