Porzucenie zmian bez usuwania z historii


180

Jest taki commit, który po prostu nie działał, więc chcę go porzucić bez usuwania go z historii .

Zaktualizowałem z wcześniejszej wersji i zobowiązałem się, tworząc w ten sposób nową głowę.


Nie mam gałęzi, nie chcę gałęzi, chcę po prostu kontynuować z nową głową dokładnie taką, jaka jest, nic szczególnego, żadnego połączenia, żadnych zmartwień, po prostu zapominam o poprzednim.

Nie mogę znaleźć sposobu, aby to zrobić i zaczynam wierzyć, że nie da się tego zrobić. Wszystko, co znajduję, to rzeczy dotyczące gałęzi lub rzeczy dotyczące łączenia.


1
Jest w twojej repozytorium, więc nie został usunięty z historii. Utworzyłeś nową głowę, więc możesz bez problemu wprowadzać poprawki. Co przeszkadza ci w kontynuowaniu pracy z nową głową?
ataylor

Jaka jest twoja awersja do gałęzi?
Andres Jaan Tack,

@Andres To nie do końca awersja do gałęzi. Po prostu potrzebowałem, aby działał bez głupiego dodatkowego kroku tworzenia takiego, aby go zamknąć.
o0 ”.

Każdy, kto czyta - należy pamiętać, że gałąź została już utworzona w tym scenariuszu; zwróć uwagę na wyjaśnienie podane w tej odpowiedzi: stackoverflow.com/a/3692607/3195477
UuDdLrLrSs

Odpowiedzi:


181

Zaktualizuj swoje repozytorium do nowej wersji, o której chcesz zapomnieć, a następnie użyj, hg commit --close-branchaby oznaczyć (anonimową) gałąź jako zamkniętą. Następnie zaktualizować do szefa oddziału, który nie ma, i kontynuować pracę.

Nadal możesz zobaczyć zamkniętą gałąź, jeśli użyjesz tej -copcji hg heads, ale domyślnie hg mergesię nie pojawi i nie będzie wiedział, że nie spróbuje połączyć się z zamkniętą głową.

Musisz użyć hg push --forcepierwszego razu, kiedy przesuwasz tę zamkniętą głowę do innego repozytorium, ponieważ w rzeczywistości tworzysz dodatkowe głowice w zdalnym repozytorium podczas pushowania. Powiedz Mercurialowi, że to w porządku --force. Ludzie, którzy pociągną za zamkniętą głowę, nie będą przeszkadzać żadnym ostrzeżeniem.


3
@Niall C. czy to nie zadziała tylko wtedy, gdy zaznaczy to jako nazwaną gałąź? Zakładam, że z tego, co powiedział, że zrobił, że jest to domyślne
msarchet

ale ... to nieprawda, wciąż dzwonię do obu głów, kiedy dzwonię hg heads... Używam mercurial 1.4.3, czy to nowsza funkcja?
o0 ”.

2
@msarchet: AFAIK, próbuję dzisiaj, --close-branch NIE działa dla anonimowych gałęzi. Powinno, ale nie musi. Mam nadzieję, że to się zmieni w niektórych przyszłych wersjach Mercurial. Anonimowe gałęzie są bardzo ładne, ale powinny być tak samo wysokiej klasy, jak nazwane gałęzie.
Krazy Glew

4
@KrazyGlew: Problem polega na tym, że „anonimowa” gałąź to tak naprawdę tylko druga gałąź o tej samej nazwie co gałąź, na której została oparta. Tak naprawdę nie próbujesz zamknąć gałęzi (nazwanej): próbujesz odrzucić wprowadzone zmiany. Innymi słowy, hg branchespowinien nadal wyświetlać nazwę gałęzi, na której jesteś. Zamiast próbować zamknąć gałąź, scal anonimową gałąź z powrotem do oryginalnej gałęzi, odrzucając wszystkie zmiany.
StriplingWarrior

2
W moim przypadku mam gałąź o nazwie default (jest to standard) i inną o nazwie default / master (myślę, że ze względu na fakt, że zdalny magazyn to tak naprawdę git). hg update default / master; hg commit --close-branch; domyślna aktualizacja hg działała dla mnie.
MattD

68

Wiem, że na tym etapie nie chcesz pracować z oddziałami, ale właśnie to zrobiłeś. Kiedy wróciłeś do wcześniejszej wersji i popełniłeś coś, co działało, utworzyłeś gałąź - gałąź bez nazwy, ale gałąź mimo wszystko.


Nie ma problemu z kontynuowaniem tego, czym jesteś, i nie martwisz się, że masz wiele głów, ale jeśli chcesz uporządkować rzeczy, aby nie przypadkowo wybrać niewłaściwą głowę, możesz zabić starą gałąź.

W dokumentacji Mercurial znajduje się dobra sekcja, która zawiera szereg opcji dotyczących przycinania martwych gałęzi .

Myślę, że najlepszą opcją jest oznaczenie starej gałęzi jako „zamkniętej”. Jeśli twoja stara głowa to wersja „123”, to:

hg update -r 123
hg commit --close-branch -m 'Closing old branch'
hg update -C default

3
Blurgh - właśnie zobaczyłem odpowiedź @ Nialla po moim wejściu. Poprze głos Nialla i moje mogą popaść w pulę punktów zerowych. :)
Nick Pierpoint

1
Bardziej podoba mi się twoja odpowiedź, wymaga mniej pogłębienia terminologii merucrial (która, jak mogę powiedzieć, wydaje się być wybrana, aby zmylić użytkowników git)
tacaswell

8
lol to odwrotnie! Terminologia mercurial została wybrana tak, aby brzmiała naturalnie dla użytkowników svn, podczas gdy git jest mylący jak diabli! tak czy inaczej, poprawiając odpowiedź, ponieważ zawiera ona ostatnią aktualizację
Tobia,

2
Dlaczego trzeba -Csię hg update? Wydawałoby się, że żadne pliki nie zostałyby zmodyfikowane, więc powinno działać bez niego.
maks.

1
o ile mogę stwierdzić, nigdzie nie potrzebujesz -C. jeśli jednak dokonujesz zaległych zmian podczas próby aktualizacji, otrzymasz przerwanie.
Eli Albert

21

Przede wszystkim wpisz:

hg heads

Wyobraź sobie, że masz na liście trzy głowy:

changeset:   223:d1c3deae6297
user:        Your name  <your@email.com>
date:        Mon Jun 09 02:24:23 2014 +0200
summary:     commit description #3

changeset:   123:91c5402959z3
user:        Your name <your@email.com>
date:        Sat Dec 23 16:05:38 2013 +0200
summary:     commit description #2

changeset:   59:81b9804156a8
user:        Your name <your@email.com>
date:        Sat Sep 14 13:14:40 2013 +0200
summary:     commit description #1

Powiedzmy, że chcesz zachować ostatnią głowę aktywną (223) i zamknąć resztę.

Następnie wykonaj następujące czynności:

Zamknij głowę # 59

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

Zamknij głowę # 123

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

Zatwierdź zmiany

hg push

Nie zapomnij przejść do prawej głowy na końcu

hg up -r 223

I jesteś skończony.


To fajny samouczek, ale przykładowe komunikaty zatwierdzania są nieco meta. Podałbym lepsze przykłady, aby osoby uczące się od Ciebie mogły przekazywać lepsze komunikaty o zatwierdzeniach. Coś jak --close-branch -m "Closing branch - technique #2 abandoned in favor of technique #3".
Jason R. Coombs

5
Co więcej, na końcu skończyłeś, tyle że twoja kopia robocza wciąż znajduje się na głowie, którą właśnie zamknąłeś. Dopuszczenie kolejnej zmiany nastąpiłoby na zamkniętej głowie, otwierając ją ponownie. Będziesz chciał hg up -r 223przed dokonaniem jakichkolwiek zmian.
Jason R. Coombs

@Jason R. Coombs: Racja!
Artur Barseghyan

według @Niall, i moje własne doświadczenie właśnie teraz, będziesz musiał hg push --force, nie tylko, hg pushaby ominąć ostrzeżenie o pchaniu wielu głów.
craq

1
@Artur Zgadzam się ogólnie. W tym przypadku hg pushsamo w sobie nie działało. W jaki sposób zaleca się wprowadzanie zmian w zewnętrznym repozytorium, jeśli odmawia z powodu wielu głowic?
craq

12

Chcesz użyć hg backout. Spowoduje to usunięcie zmian wprowadzonych przez zestaw zmian z dowolnego zestawu podrzędnego.

Sprawdź to, aby uzyskać dobre wyjaśnienie. Wycofanie się z rtęci


2
To jest właściwa odpowiedź. Wycofanie dodaje odwrotność zestawu zmian, cofając działającą i dając komunikat zatwierdzenia, aby przypomnieć sobie, dlaczego nie podobał ci się ten pomysł.
Ry4an Brase,

7
Właściwie nie zgadzam się - porzucenie pracy nad jedną głową i rozpoczęcie od dobrego punktu wyjścia wydaje się czystszym wzorcem pracy niż używanie wycofań. Zwłaszcza, że ​​nie można wycofać więcej niż jednego zestawu zmian na raz.
Martin Geisler,

1
@Martin Geisler, cóż, ogólnie się z tym zgadzam, ale OP stwierdził, że chce zrezygnować ze zmian bez oddziałów
msarchet

2
@Martin Geisler tak, jestem za rozgałęzianiem się, tylko czasami nukanie złej zmiany jest najlepsze
msarchet

1
Czasami może się przydać, ale tak naprawdę nie tego chciałem. W każdym razie dzięki :)
o0 '.

2

Zarówno odpowiedzi Nialla, jak i Nicka są proste. Ponieważ przyłapuję się na tworzeniu wielu zwisających głów, łatwiej napisałem alias do zamykania głów. Dodając to do .hgrc:

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

(jeśli masz już [alias]sekcję, możesz do niej dołączyć)

Możesz teraz zamknąć głowicę jednym poleceniem (i bez konieczności ręcznego aktualizowania innego zestawu zmian) w następujący sposób:

$ hg behead 123

Uwaga: alias wykorzystuje fakt, że aliasy Mercurial mogą być poleceniami powłoki . Oznacza to, że prawdopodobnie będzie to działać tylko w systemie UNIX, a nie w systemie Windows.


2

Alternatywą dla zamykania lub usuwania niechcianej gałęzi byłoby połączenie jej w sposób, który całkowicie odrzuca jej skutki, ale pozostawia ją w historii. Takie podejście umożliwi rozprzestrzenianie się niechcianych zmian w trybie wypychania - więc używaj tego tylko wtedy, gdy jest to zamierzony efekt.

Powiedzmy, że historia zestawu zmian wygląda następująco:

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

i jest 5i 6które nie są już potrzebne.

Możesz to zrobić:

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

który stworzy to:

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

Aktualizacja 8zapewniająca, że ​​pracujesz nad żądanym szefem w historii, który chcesz zachować.

-t :localInstruuje hg, aby użył „narzędzia” scalania o nazwie local, które każe mu zignorować zmiany z drugiej gałęzi, tj. Tej , która NIE jest reprezentowana przez bieżący stan folderu roboczego. Więcej informacji .

W ten sposób niepożądane zmiany 5i 6zachowały się w historii, ale nie wpływają na coś nowszego.


2

Jest to przypadek użycia rozszerzenia Evolve . Obecnie nie jest dołączony do Mercurial, więc technicznie jest rozszerzeniem strony trzeciej. Ale jest dość intensywnie wykorzystywany przez grupę ludzi, w tym programistów Mercurial, jest bardzo aktywnie rozwijany i nigdzie się nie wybiera.

Dzięki rozszerzeniu Evolve po prostu to robisz

hg prune -r revname

i kontynuuj swoje życie. Zestaw nadal będzie tam, ale nieaktualny. Nie będzie widoczny, chyba że przekażesz tę --hiddenopcję komendom Mercurial, a domyślnie nie zostanie przekazany do zdalnych repozytoriów. Chociaż myślę, że możesz to zmusić, jeśli naprawdę chcesz.

Jeśli zestaw, który przycinasz, ma przodków, których chcesz zachować, będziesz musiał uruchomić, hg evolveaby zmienić bazę tych zmian. hg evolvezrobi to automatycznie. W przeciwnym razie nie musisz nic robić.


1

Możesz sklonować swoje zepsute repo do nowego bez klonowania tej niechcianej głowy. Następnie usuń stare repozytorium, przenieś nowo utworzony klon do pierwotnego miejsca i kontynuuj pracę z nim. To zajmie trochę czasu, ale otrzymasz idealnie czyste repozytorium bez oznak tej niechcianej wersji.

hg clone --rev myGoodResition myDirtyRepo myCleanRepo

1
Przepraszam, nie o to prosiłem.
o0 ”.

4
@Kristof: czy to żart? Ponownie przeczytaj pierwszy wiersz mojego postu: „porzuć go bez usuwania go z historii
o0 ”.

-1

Natrafiłem na ten problem wiele razy, gdy chcę ściąć głowę, która została utworzona przez pomyłkę. Zawsze chcę zobaczyć, jak znika z powierzchni Ziemi.

Na lokalnej kopii pobierz najnowszą wersję, a następnie:

  1. Znajdź początek głowy, którą chcesz rozebrać (gdzie nowa szyja zaczyna się rozgałęziać), uzyskaj numer wersji

  2. Rozbierz to.


Źródło: TipsAndTricks .

Źródło: PruningDeadBranches # Using_strip .

hg --config extensions.hgext.mq= strip -n <rev>
  1. Dokonaj trywialnej aktualizacji pliku (dodaj spację do pliku), zatwierdź i wypchnij.

Twoje repozytorium powinno być teraz pozbawione głowy. Ostatni krok jest ważny, ponieważ stripping nie powoduje żadnych zmian, które można przekazać do centralnego repozytorium. Bez ostatniego kroku rozebrałeś głowę tylko lokalnie.


1
Ale wypychanie nigdy nie usuwa niczego ze zdalnego repozytorium. Dodaje tylko informacje. Jeśli zestaw zmian znajduje się już w centralnym repozytorium, musisz użyć rozszerzenia evolve lub w jakiś sposób rozebrać go na samym serwerze centralnym. Jeśli zestaw zmian nie znajduje się już w centralnym repozytorium, wystarczy usunąć go lokalnie bez konieczności wypychania.
Ben
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.