Pytanie Cofanie bazy git


Czy ktoś wie, jak łatwo cofnąć git rebase?

Jedynym sposobem, który przychodzi na myśl, jest ręczne przejście do niego:

  • git checkout commit parent dla obu oddziałów
  • następnie stwórz gałąź temp
  • cherry-pick wszystkie zatwierdzenia ręcznie
  • zastępuje gałąź, w której zostałam ponownie oparta przez ręcznie utworzoną gałąź

W mojej obecnej sytuacji będzie to działało, ponieważ mogę łatwo zauważyć zaręczyny z obu gałęzi (jedna była moimi rzeczami, druga to rzeczy mojego kolegi).

Jednak moje podejście wydaje mi się nieoptymalne i podatne na błędy (załóżmy, że właśnie wybrałem 2 moje własne gałęzie).

Jakieś pomysły?

Wyjaśnienie: mówię o przegrupowaniu, podczas którego powtórzono kilka poprawek. Nie jedyny.


2434
2017-09-25 17:59


pochodzenie


Zauważ też, że podczas rebase możesz wykluczyć commit lub zgnieść je; zmiany te nie można cofnąć bez wskaźnika do oryginalnych węzłów lub przeszukiwania refloga, więc wiśnia nie zadziałałaby. - ANeves
stackoverflow.com/a/692763/2458438 Najlepiej byłoby to zaakceptowaną odpowiedzią. - DDM


Odpowiedzi:


Najprostszym sposobem byłoby znalezienie zatwierdzenia head oddziału, tak jak było to bezpośrednio przed rozpoczęciem reorganizacji w reflog...

git reflog

i zresetować bieżącą gałąź do niego (ze zwykłymi zastrzeżeniami dotyczącymi absolutnej pewności przed resekcją z --hard opcja).

Załóżmy, że stare zatwierdzenie było HEAD@{5} w dzienniku ref:

git reset --hard HEAD@{5}

W systemie Windows może być konieczne podanie odniesienia:

git reset --hard "HEAD@{5}"

Możesz sprawdzić historię starej głowy kandydata, po prostu robiąc a git log HEAD@{5} (Windows:  git log "HEAD@{5}").

Jeśli nie jesteś wyłączony przez jeden z protokołów branżowych, powinieneś być w stanie to zrobić git reflog branchname@{1} jako rebase odłącza głowę oddziału przed ponownym podłączeniem do ostatecznej głowicy. Sprawdziłbym to podwójnie, chociaż ostatnio tego nie zweryfikowałem.

Domyślnie wszystkie reflogi są aktywowane w repozytoriach nieprzypadkowych:

[core]
    logAllRefUpdates = true

3371
2017-09-25 19:56



Git reflog jest niesamowity, pamiętaj tylko, że możesz uzyskać lepsze sformatowane wyjście git log -g (wskazówka od Scotta Chacona progit.org/book). - karmi
@Zach: git rebase --abort (-i nie ma sensu --abort) służy do rezygnacji z reorganizacji, która nie została zakończona - albo z powodu konfliktów, albo z powodu interakcji lub obu; nie chodzi tu o cofnięcie skutecznego rebase, o to właśnie chodzi. Można albo użyć rebase --abort lub reset --hard w zależności od sytuacji, w której się znajdowałeś. Nie powinieneś robić obu tych rzeczy. - CB Bailey
Dzięki! W mojej instalacji Gita musiałem umieścić "HEAD {22}" w cudzysłowie, żeby zadziałało. - SidJ
To uratowało mi życie ... niestety, w moim haste Zrobiłem git reset --hard HEAD@{5} - co było dwoma zobowiązaniami powyżej tego, co chciałem zrobić. Nie trzeba dodawać, dzięki Bogu za Gita, który pozwolił mi po prostu iść do przodu i dokonać tej poprawki, po wykonaniu innej git reflogi zdałem sobie sprawę, że zobowiązanie, do którego chciałem się udać, zostało przesunięte o 1, szybko to poprawiłem i wszystko jest w porządku. =) - marcamillion
Na wszelki wypadek najpierw wykonaj kopię zapasową: git tag BACKUP. Możesz wrócić do niego, jeśli coś pójdzie nie tak: git reset --hard BACKUP - kolypto


W rzeczywistości, rebase zapisuje twój punkt wyjścia do ORIG_HEAD więc jest to zwykle tak proste, jak:

git reset --hard ORIG_HEAD

Jednakże reset, rebase i merge wszystko zapisz oryginał HEAD wskaźnik do ORIG_HEAD więc jeśli wykonałeś którekolwiek z tych poleceń od rebase, którą próbujesz cofnąć, będziesz musiał użyć refloga.


1169
2018-03-28 13:24



Dzięki. To pomogło mi wrócić do squasha! - kakyo
W razie ORIG_HEAD nie jest już przydatny, możesz również użyć branchName@{n} składnia, gdzie n jest n-tą wcześniejszą pozycją wskaźnika gałęzi. Na przykład, jeśli zmienisz bazę featureA rozgałęzienie na swoje master oddziału, ale nie podoba ci się wynik przebicia, możesz to po prostu zrobić git reset --hard featureA@{1} aby zresetować gałąź z powrotem do miejsca, w którym znajdowała się przed wykonaniem reorganizacji. Możesz przeczytać więcej na temat składni gałęzi {{}} na stronie oficjalne dokumenty Git dotyczące korekt.
To jest najłatwiejsze. Podążaj za nim za pomocą a git rebase --abort chociaż. - Seph
To powinna być akceptowana odpowiedź IMO. - Tomáš Fejfar
ORIG_HEAD jest BARDZO BARDZO przydatny, jeśli właśnie zrobiłeś rebase i chcesz go przywrócić w zdrowy i spokojny sposób. Powinna to być odpowiedź TOP VOTED (lub też zaakceptowana odpowiedź). Potrzebuje uderzenia. Najlepsza głosowana odpowiedź, która prosi o zrobienie git reset --hard HEAD@{5} wiąże się z niepotrzebnym liczeniem głosów, które ma więcej możliwości popełnienia błędu. - DDM


Odpowiedź Charlesa działa, ale możesz chcieć to zrobić:

git rebase --abort

czyścić po reset.

W przeciwnym razie możesz otrzymać wiadomość "Interactive rebase already started".


320
2017-07-27 18:21



Ten usunął część "| REBASE" w moim podpowiedzi. +1 - Wouter Thielen
Myślę, że tak powinno być git rebase --abort w (w zależności od wersji git być może). - Seph
To nie było pytanie. Pytanie pyta, jak cofnąć ukończony rebase. - Arunav Sanyal
@ArunavSanyal to ostatnia nadzieja, jeśli cofnięcie się nie powiodło ... - aswzen


Zresetowanie gałęzi do zwisającego obiektu commit starej końcówki jest oczywiście najlepszym rozwiązaniem, ponieważ przywraca poprzedni stan bez wysiłku. Ale jeśli zdarzyło ci się, że utraciłeś te zatwierdzenia (np. Dlatego, że w międzyczasie zbierzesz śmieci do swojego repozytorium lub jest to świeży klon), zawsze możesz ponownie utworzyć oddział ponownie. Kluczem do tego jest --onto przełącznik.

Załóżmy, że masz wyimaginowaną nazwę tematu topic, że rozgałęziłeś się master kiedy końcówka master było 0deadbeef popełnić. W pewnym momencie na topic Oddział, zrobiłeś git rebase master. Teraz chcesz to cofnąć. Oto jak:

git rebase --onto 0deadbeef master topic

Spowoduje to włączenie wszystkich zatwierdzeń topic które nie są włączone master i odtwarzaj je na wierzchu 0deadbeef.

Z --onto, możesz zmienić swoją historię w prawie dowolny kształt.

Baw się dobrze. :-)


75
2017-09-26 02:08



Myślę, że jest to najlepsza opcja ze względu na jej elastyczność. Rozgałęziłem b1 off master, a następnie przerzuciłem b1 na nowy branch b2, a następnie chciałem przywrócić b1 na bazie master. Po prostu uwielbiam git - dzięki! - ripper234
To najlepsza opcja tutaj! Zachował wszystkie zmiany, które mam na mojej obecnej gałęzi, i usunął wszystkie niechciane! - Alicia Tang
Powiedziałbym to z kombinacją --onto i -i możesz zmienić swoją historię w prawie dowolny kształt. Użyj gitk (lub gitx na mac), aby zobaczyć kształty, które tworzysz :-). - rjmunro


Właściwie umieściłem znacznik zapasowy na gałęzi, zanim wykonam jakąś nietrywialną operację (większość rebase jest banalna, ale zrobiłbym to, gdyby wyglądała nigdzie złożona).

Następnie przywracanie jest tak proste, jak git reset --hard BACKUP.


62
2018-05-12 20:57



Ja też to robię. Przydatne jest również, aby git diff BACKUP..HEAD sprawił, że zmieniłeś to, co chciałeś. - Paul Bone
Zrobiłem to również, ale ponieważ lepiej czuję się z reflogem, nie czuję już potrzeby. Reflog zasadniczo robi to w twoim imieniu za każdym razem, gdy zmieniasz HEAD. - Pete Hodgson
Cóż, ja wolę wymowne nazwy, ponieważ wyszukiwanie odpowiedniego elementu w reflogu czasami nie jest zabawne. - Alex Gontmakher
Nie musisz nawet tworzyć kopii zapasowej gałęzi, możesz po prostu użyć branchName@{n} składnia, tutaj n jest n-tą wcześniejszą pozycją wskaźnika gałęzi. Na przykład, jeśli zmienisz bazę featureA rozgałęzienie na swoje master oddziału, ale nie podoba ci się wynik przebicia, możesz to po prostu zrobić git reset --hard featureA@{1} aby zresetować gałąź z powrotem do miejsca, w którym znajdowała się przed wykonaniem reorganizacji. Możesz przeczytać więcej o branch@{n} składnia w oficjalne dokumenty Git dotyczące korekt.
Właściwie nie musisz nawet używać powyższej składni, zgodnie z Odpowiedź Pat Notza, oryginalny HEAD oddziału jest tymczasowo przechowywane w ORIG_HEAD. Ale technika używania etykiety gałęzi kopii zapasowej działa również, to tylko więcej kroków.


W razie popchnąłeś swoją gałąź do zdalnego repozytorium (zazwyczaj jest to pochodzenie), a następnie wykonałeś pomyślny rebase (bez scalania) (git rebase --abort daje "Nie ma żadnego oporu w toku") możesz łatwo zresetuj gałąź za pomocą dowództwo:

git reset --hard origin / {branchName}

Przykład:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

53
2017-09-28 12:43



To jest właściwa odpowiedź dla mnie. Rebase i commit przed rebase miały ten sam identyfikator commit, a powrót do HEAD {1} po prostu nie powróciłby do rebase! - Bill Kotsias


W przypadku, gdy nie ukończyłeś repertuaru i w jego środku, wykonano następujące prace:

git rebase --abort

49
2017-10-15 20:20



To działało dla mnie. Miałem konflikty, więc zakwalifikowałem je jako "w środku". - Fakeer


W przypadku wielu zatwierdzeń pamiętaj, że każde zatwierdzenie odwołuje się do historii poprzedzającej zatwierdzenie. Tak więc w odpowiedzi Karola, przeczytaj "stary commit" jako "najnowszy ze starych zobowiązań". Jeśli zresetujesz do tego zatwierdzenia, cała historia prowadząca do tego zatwierdzenia pojawi się ponownie. To powinno robić, co chcesz.


14
2017-09-25 21:36



To prawda, dzięki za przypomnienie ;-) - webmat


Za pomocą reflog nie działa dla mnie.

To, co zadziałało, było podobne do opisanego tutaj. Otwórz plik w pliku .git / logs / refs nazwanym po gałęzi, która została przejęta i znajdź wiersz zawierający "rebase finsihed", coś takiego:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

Sprawdź drugie zatwierdzenie wymienione na linii.

git checkout 88552c8f

Po potwierdzeniu to zawierało moje utracone zmiany, rozgałęziłem się i odetchnąłem z ulgą.

git log
git checkout -b lost_changes

14
2018-02-20 13:59



albo to: stackoverflow.com/questions/1108853/... - cregox
Whoa - z tego linku "Jest jedno zastrzeżenie: straciłem historię oddziału, ale w tym przypadku tak naprawdę nie miało to znaczenia, byłem po prostu szczęśliwy, że odzyskałem moje zmiany." ? - ruffin


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  (zanotuj -ja) Musiałem po prostu zrobić git rebase --abort (bez  -ja).

Używanie obu -i i --abort w tym samym czasie powoduje, że Git pokazuje mi listę użycia / opcji.

Mój poprzedni i aktualny status oddziału w tym rozwiązaniu to:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

11
2018-03-11 21:26