Czy ktoś wie, jak łatwo cofnąć bazę git?
Jedyny sposób, który przychodzi na myśl, to podejść ręcznie:
- git wypisanie elementu nadrzędnego zatwierdzenia do obu gałęzi
- następnie stwórz gałąź temp stamtąd
- wybierz wszystkie zobowiązania ręcznie
- zastąp gałąź, w której bazowałem ponownie, ręcznie utworzoną gałęzią
W mojej obecnej sytuacji to zadziała, ponieważ mogę łatwo wykryć zatwierdzenia z obu gałęzi (jeden był moim, a drugi moim kolegą).
Jednak moje podejście wydaje mi się nieoptymalne i podatne na błędy (powiedzmy, że właśnie bazowałem na 2 własnych gałęziach).
Jakieś pomysły?
Wyjaśnienie: Mówię o bazie, podczas której odtwarzano kilka zmian. Nie jedyny.
git
rebase
git-rebase
undo
webmat
źródło
źródło
Odpowiedzi:
Najłatwiejszym sposobem byłoby znalezienie zatwierdzenia głównego oddziału, ponieważ było to bezpośrednio przed uruchomieniem bazy w rejestrze ...
i zresetować do niej bieżącą gałąź (ze zwykłymi zastrzeżeniami dotyczącymi absolutnej pewności przed resetowaniem z
--hard
opcją).Załóżmy, że stary zatwierdzenie znajduje się
HEAD@{5}
w dzienniku referencyjnym:W systemie Windows może być konieczne zacytowanie referencji:
Możesz sprawdzić historię starej głowy kandydata, wykonując
git log HEAD@{5}
( Windowsgit log "HEAD@{5}"
:).Jeśli nie wyłączyłeś ponownego rejestrowania gałęzi, powinieneś być w stanie to zrobić,
git reflog branchname@{1}
ponieważ rebase odłącza głowę gałęzi przed ponownym podłączeniem do ostatniej głowy. Chciałbym dokładnie to sprawdzić, ponieważ nie sprawdziłem tego ostatnio.Domyślnie wszystkie dzienniki logowania są aktywowane dla repozytoriów innych niż zwykłe:
źródło
git log -g
(wskazówka progit.org/book Scotta Chakona ).git rebase --abort
(-i
nie ma sensu z--abort
) służy do porzucenia bazy, która nie została ukończona - albo z powodu konfliktów, albo dlatego, że była interaktywna, albo obie; pytanie nie polega na cofnięciu udanego rebase'u. Możesz użyćrebase --abort
albo wreset --hard
zależności od sytuacji, w której się znalazłeś. Nie powinieneś robić obu tych rzeczy.git tag BACKUP
. Możesz do niego wrócić, jeśli coś pójdzie nie tak:git reset --hard BACKUP
commit:
a nierebase:
. Brzmi oczywisto, ale trochę mnie to zamieszało.git reset --hard ORIG_HEAD
zrobiłby tego lewy zaraz po przypadkowym zwrocie?W rzeczywistości rebase zapisuje punkt początkowy,
ORIG_HEAD
więc jest to zwykle tak proste, jak:Jednakże
reset
,rebase
imerge
wszystko Zapisz oryginalnegoHEAD
wskaźnik doORIG_HEAD
tak, jeśli zrobiłeś żadnej z tych poleceń od rebase starasz cofnąć następnie będziesz musiał użyć reflog.źródło
ORIG_HEAD
nie jest już użyteczny, możesz również użyćbranchName@{n}
składni, gdzien
n-ta poprzednia pozycja wskaźnika gałęzi. Na przykład, jeśli zmieniszfeatureA
gałąź na swojąmaster
gałąź, ale nie podoba ci się wynik bazy, możesz po prostugit reset --hard featureA@{1}
zresetować gałąź z powrotem dokładnie tam, gdzie była przed dokonaniem zmiany bazy. Możesz przeczytać więcej o składni gałęzi @ {n} w oficjalnych dokumentach Git dotyczących poprawek .git rebase --abort
jednak.git 2.17.0
.git reset --hard ORIG_HEAD
mogę używać wielokrotnie, aby cofać się raz po raz. Powiedz, jeśli A --- zmiana podstawy na --- B --- zmiana podstawy na --- C, teraz jestem w C, mogę wrócić do A, używając dwa razygit reset --hard ORIG_HEAD
git rebase --abort
?Odpowiedź Charlesa działa, ale możesz to zrobić:
posprzątać po
reset
.W przeciwnym razie może zostać wyświetlony komunikat „
Interactive rebase already started
”.źródło
Zresetowanie gałęzi do wiszącego obiektu zatwierdzania starej końcówki jest oczywiście najlepszym rozwiązaniem, ponieważ przywraca poprzedni stan bez wysiłku. Ale jeśli zdarzyło Ci się zgubić te zatwierdzenia (np. Ponieważ w międzyczasie zrzuciłeś swoje repozytorium, lub jest to świeży klon), zawsze możesz ponownie zmienić podstawę gałęzi. Kluczem do tego jest
--onto
przełącznik.Powiedzmy, że masz gałąź tematyczną z wyobraźnią
topic
, którą rozgałęziłeś,master
gdy końcówkąmaster
było0deadbeef
zatwierdzenie. W pewnym momencie, kiedytopic
byłeś na gałęzi, zrobiłeś togit rebase master
. Teraz chcesz to cofnąć. Oto jak:Spowoduje to wzięcie wszystkich zatwierdzeń
topic
, które nie są włączonemaster
i odtworzenie ich na wierzchu0deadbeef
.Dzięki
--onto
możesz zmienić swoją historię w praktycznie dowolny kształt .Baw się dobrze. :-)
źródło
--onto
i-i
możesz zmienić swoją historię w prawie dowolny kształt. Użyj gitk (lub gitx na Macu), aby zobaczyć kształty, które tworzysz :-).W rzeczywistości umieszczam tag zapasowy na gałęzi, zanim wykonam jakąś nierywalną operację (większość zmian w bazie jest trywialna, ale zrobiłbym to, jeśli wygląda gdziekolwiek złożona).
Następnie przywracanie jest tak proste, jak
git reset --hard BACKUP
.źródło
branchName@{n}
składni, oton
n-ta poprzednia pozycja wskaźnika gałęzi. Na przykład, jeśli zmieniszfeatureA
gałąź na swojąmaster
gałąź, ale nie podoba ci się wynik bazy, możesz po prostugit reset --hard featureA@{1}
zresetować gałąź z powrotem dokładnie tam, gdzie była przed dokonaniem zmiany bazy. Możesz przeczytać więcej obranch@{n}
składni w oficjalnych dokumentach Git dotyczących poprawek .HEAD
gałęzi jest tymczasowo przechowywanyORIG_HEAD
. Ale technika użycia zapasowej etykiety oddziału również działa, to tylko kolejne kroki.W przypadku , gdy wypchnąłeś swoją gałąź do zdalnego repozytorium (zwykle jest to jej początek), a następnie wykonałeś udany rebase (bez scalania) (
git rebase --abort
daje „No rebase in progress”), możesz łatwo zresetować gałąź za pomocą polecenia:Przykład:
źródło
Korzystanie
reflog
nie działało dla mnie.To, co zadziałało, było podobne do opisanego tutaj . Otwórz plik w .git / logs / refs nazwany na podstawie gałęzi, która została ponownie wydana, i znajdź wiersz zawierający „sfinalizowany rebase”, coś w stylu:
Kasy drugiego zatwierdzenia wymienionego w wierszu.
Po potwierdzeniu, że zawiera moje utracone zmiany, rozgałęziłem się i odetchnąłem z ulgą.
źródło
W przypadku wielu zatwierdzeń pamiętaj, że wszelkie zatwierdzenia odwołują się do całej historii prowadzącej do tego zatwierdzenia. Tak więc w odpowiedzi Karola, należy przeczytać „stare zatwierdzenie” jako „najnowsze ze starych zatwierdzeń”. Jeśli zresetujesz to zatwierdzenie, cała historia prowadząca do tego zatwierdzenia pojawi się ponownie. To powinno zrobić, co chcesz.
źródło
Po rozwiązaniu @Allan i @Zearin chciałbym po prostu zrobić komentarz, ale nie mam wystarczającej reputacji, więc użyłem następującego polecenia:
Zamiast robić
git rebase -i --abort
(uwaga -i ) Musiałem po prostu zrobićgit rebase --abort
( bez -i ).Używając obu
-i
i--abort
jednocześnie powoduje Git, aby pokazać mi listę wykorzystanie / opcji.Tak więc mój poprzedni i aktualny status oddziału z tym rozwiązaniem to:
źródło
Jeśli udało Ci się dokonać repartycji przeciwko zdalnemu oddziałowi i
git rebase --abort
nadal nie możesz, możesz wykonać kilka sztuczek, aby zapisać swoją pracę i nie mieć wymuszonych wypchnięć. Załóżmy, że twoja obecna gałąź, która została przez pomyłkę zwolniona, nazywa sięyour-branch
i śledziorigin/your-branch
git branch -m your-branch-rebased
# zmień nazwę bieżącej gałęzigit checkout origin/your-branch
# kasy do najnowszego stanu, o którym wiadomo, że pochodzigit checkout -b your-branch
git log your-branch-rebased
, porównajgit log your-branch
i zdefiniuj brakujące zatwierdzeniayour-branch
git cherry-pick COMMIT_HASH
za każde zatwierdzenie wyour-branch-rebased
remote/your-branch
i należy tylko wypychaćyour-branch
źródło
Powiedzmy, że dokonuję zmiany bazy na mój dział funkcji i otrzymuję 30 nowych zatwierdzeń, które coś psują. Przekonałem się, że często najłatwiej jest po prostu usunąć złe zatwierdzenia.
Interaktywny rebase dla ostatnich 31 zatwierdzeń (nie boli, jeśli wybierzesz zdecydowanie za dużo).
Po prostu weź commity, których chcesz się pozbyć i oznacz je „d” zamiast „pick”. Teraz zatwierdzenia są skutecznie usuwane, cofając zmianę bazy (jeśli usuniesz tylko zatwierdzenia, które właśnie otrzymałeś podczas zmiany bazy).
źródło
Dla początkujących / każdego, kto zbytnio boi się twardego resetu, możesz pobrać zatwierdzenie z dziennika, a następnie zapisać go jako nowy oddział.
Znajdź zatwierdzenie tuż przed rozpoczęciem bazowania. Może być konieczne przewinięcie w dół, aby je znaleźć (naciśnij Enter lub PageDown). Zanotuj numer HEAD i zastąp 57:
Przejrzyj gałąź / zatwierdzenia, jeśli wygląda dobrze, utwórz nową gałąź za pomocą tego HEAD:
źródło
Jeśli jesteś na oddziale, możesz użyć:
Istnieje nie tylko dziennik referencyjny HEAD (uzyskany przez
git reflog
), ale także dzienniki referencyjne dla każdej gałęzi (otrzymane przezgit reflog <branch>
). Tak więc, jeśli jesteś włączony,master
togit reflog master
wyświetli listę wszystkich zmian w tej gałęzi. Można odwołać się do tego, by zmianymaster@{1}
,master@{2}
itpgit rebase
zwykle zmienia HEAD wiele razy, ale bieżąca gałąź zostanie zaktualizowana tylko raz.@{1}
jest po prostu skrótem do bieżącej gałęzi , więc jest równy,master@{1}
jeśli jesteś włączonymaster
.git reset --hard ORIG_HEAD
nie będzie działać, jeśli korzystałeśgit reset
podczas interaktywnegorebase
.źródło
Zwykle robię to
git reset #commit_hash
do ostatniego zatwierdzenia, gdzie myślę, że rebase nie przyniosło żadnego efektu.
następnie
git pull
Teraz twoja gałąź powinna pasować dokładnie tak samo jak master, a zmiany w repbased nie powinny w niej być.
Teraz można po prostu wybrać commits na tej gałęzi.
źródło
Wypróbowałem wszystkie sugestie po zresetowaniu i ponownym zalogowaniu bez powodzenia. Przywrócenie lokalnej historii IntelliJ rozwiązało problem utraconych plików
źródło
git reset --hard origin / {branchName}
jest poprawnym rozwiązaniem, aby zresetować wszystkie lokalne zmiany dokonane przez rebase.
źródło
origin/branch
utratę zmian między HEAD a tym punktem. Ogólnie nie chcesz tego.Jeśli coś zepsujesz w ramach bazy danych git, np.
git rebase --abort
Gdy masz nieprzydzielone pliki, zostaną one utracone igit reflog
nie pomogą. To mi się przydarzyło i musisz pomyśleć tutaj nieszablonowo. Jeśli masz szczęście, jak ja i korzystasz z IntelliJ Webstorm, możeszright-click->local history
i możesz przywrócić poprzedni stan pliku / folderów bez względu na to, jakie błędy popełniłeś przy oprogramowaniu do wersji. Zawsze dobrze jest mieć kolejny działający bezpiecznie.źródło
git rebase --abort
Przerywa aktywną rebase, nie cofnąć się rebase. Również używanie dwóch VCS w tym samym czasie jest złym pomysłem. Jest to miła funkcja w oprogramowaniu Jetbrains, ale nie powinieneś używać obu. Lepiej jest po prostu nauczyć się Git, szczególnie podczas odpowiadania na pytania dotyczące przepełnienia stosu, które dotyczą Git.