2015-07-04 11 views
17

Mam prosty problem. Przypadkowo popełniłem commit do mojego lokalnego repozytorium. Nie pchnąłem ani nie pociągnąłem, ani niczego innego od czasu zatwierdzenia. Jak cofnąć to zatwierdzenie i przywrócić kopię roboczą do stanu sprzed zatwierdzenia, aby móc zrobić to, co powinienem był zrobić?Mercurial: jak cofnąć ostatnie zanurzenie commit?

Można podejrzewać, że jest to duplikat, więc będę tłumaczyć dlaczego następujące pytania są różne, czy nie jest odpowiedź na moje pytanie:

Mercurial undo last commit

Odpowiedź do tego państwa, które można to zrobić z hg commit --amend, ale nie wyjaśnia, jak , jak lub podać przykład tego. Pomoc mercurail też jej nie wyjaśnia.

How do you "rollback" last commit on Mercurial?

członkowskie do korzystania hg rollback. To polecenie jest najwyraźniej przestarzałe, mimo to próbowałem go używać, ale otrzymałem komunikat: brak dostępnych informacji o cofnięciu. Szkoda, że ​​to nie działa, ponieważ byłby to naprawdę intuicyjny sposób osiągnięcia tego, czego chcę.

Edycja 1

Aby być bardziej konkretne, popełniłem wiele zmian w plikach, kiedy naprawdę chcę popełnić je jeden po drugim. Jak mogę wrócić, abym mógł to zrobić?

Odpowiedz

23

Mówiąc w języku git, jesteś patrząc pod kątem git reset --mixed HEAD^
hard by odrzucić zmiany, dzięki czemu praca „zniknąć” (zakładam, że nie jest opcją)
soft by cofnąć popełnić, ale należy wcześniej popełnione pliki indeksowane (to znaczy śledzone)
mixed zachowuje zmienione pliki w miejscu, ale informuje indeks, aby cofnąć zatwierdzenie. w git-speak: git st powiedzieliby: Changes not staged for commit

Jak to osiągnąć w mercurial/hg? Należy odpowiedzieć Mercurial (hg) equivalent of git reset (--mixed or --soft)

hg strip --keep --rev .
--keep: do not modify working directory during strip
--rev . (kropka oznacza ostatni popełnić.odczytać odpowiedź sid0 w sprawie potomków)

Zobacz również git-reset docs, Difference git reset soft/mixed, git/hg Command equivalence table

19

Ok, myślę, że znalazłem odpowiedź, jest to, aby umożliwić rozszerzenie strip i użyć następującego polecenia:

hg strip -r -1 --keep 

Ten paskach ostatnią wersję z repostiory (The -r -1 bit), a Opcja --keep oznacza brak zmian w kopii roboczej. Tak więc kończy się to kopiowaniem roboczym dokładnie tak, jak było tuż przed zatwierdzeniem i brakiem ostatniego zatwierdzenia w repozytorium.

Nie jestem ekspertem mercury, więc używaj na własne ryzyko.

+3

1. JFYI '--keep' potrzebne tylko wtedy, gdy zostały zmodyfikowane Dir pracę i chcą zachować te zmiany. Jeśli chcesz "...odzyskaj kopię roboczą do stanu, w którym znajdował się przed zatwierdzeniem ", możesz pominąć --keep 2." Polecenie strip usuwa określone zestawy zmiennych i wszystkich ich potomków "- to twoja sprawa (usuwanie wskazówka) nie jest istotne, ale w często zdarza się, że indywidualne usuwanie commitów w środku historii może być lepsze dzięki rozszerzeniu 'histedit' –

+1

Cóż, aby przywrócić kopię roboczą do stanu, w którym była tuż przed tym, jak ją popełniłem, konieczne jest użycie' --keep', w przeciwnym razie wracają do poprzedniego zatwierdzenia, a nie do stanu, w którym znajdowało się tuż przed tym zatwierdzeniem. – crobar

1

Co bym zrobił w tej sytuacji zrobić nowy oddział, który ma zmiany chcę zanim kiedykolwiek myślał o usunięciu złe Change- zestaw. Tak więc w tym przypadku będę musiał wrócić do wersji przed wykonaniem złego zatwierdzenia, ponownie wprowadzić zmiany, a następnie wprowadzić wiele zatwierdzeń, po jednym dla każdego pliku.

Krok po kroku:

1) Wróć do przed złym popełnić.

% cd <top of repo> 
% hg log -l 5 
<identify the last good revision> 
% hg update -r <last good revision number> 

2) Ponownie wykonaj zmiany: dostanę łatkę opisującą zmiany, które chcę i zastosuję do drzewa. (Zakładam, że wskazówka obecnie wskazuje gdzie zaczęliśmy)

% hg diff -r .:tip | patch -p1 
patching file a/b/c/d 
patching file a/b/e/f 

3) Dodać nowe rewizje: Jesteśmy teraz z powrotem w stanie przed wprowadzeniem commit chciał rozdzielić. Wykonaj hg status i spójrz na zmodyfikowane pliki, upewnij się, że wszystko jest zgodne z oczekiwaniami. W tym momencie możesz zatwierdzić pliki jeden po drugim, nazywając je w wierszu poleceń lub użyć rozszerzenia, takiego jak record lub crecord, aby je interaktywnie zaznaczyć.

% hg commit a/b/c/d 
% hg commit a/b/e/f 

... albo ...

% hg crecord 
<select files in UI> 
% hg crecord 
<select files in UI> 

Skończysz z repo, które wygląda następująco:

o----o----B 
     \ 
     \ 
     --o----o----o----T 

gdzie B jest stary zły popełnić, i T to nowa porada repozytorium. Jeśli chcesz, aby następnie dokonać że jako oddział zamknięty, więc nie pojawiają się w dziennikach/etc, można ...

% hg update -r <revision B> 
% hg commit --close_branch 
% hg update -r tip 

jeśli chcesz go usunąć całkowicie, można ją rozebrać.

% hg strip -r <revision B> 

Tak czy inaczej, dziennik będzie wyglądać tak, jak nigdy nic.

0

komentowanie i opracowywanie posta @ crobara Przyczyna # znaków to za mało.

podczas wykonywania lokalnego zatwierdzenia (bez naciśnięcia), a następnie uruchomienia hg strip -r -1 --keep, usuwa poprzednie zatwierdzenie ORAZ zachowuje listę plików oczekujących na zatwierdzenie. w zasadzie jest to pełne cofnięcie. jeśli używam hg stripe -r -1 bez --keep, to nadal usuwa poprzednie zatwierdzenie, ale gdy próbuję wyświetlić listę plików do zatwierdzenia, nie mogę znaleźć zmiany, więc nie polecałbym tego.

jeśli wykonam commit to wykonaj push (na odległość), a następnie wykonaj hg strip -r -1 --keep, robi dokładnie to, co powinien zrobić, ALE gdy wykonasz inny commit, a następnie push, tworzy on kolejną gałąź.

I.E. 

o----o----Branch(local) 
     \ 
     \ 
     --o----o----o----Branch(with previous push) 

moje źródło/referencje: testowanie tych scenariuszy