Pytanie Cofnij połączenie Git, które nie zostało jeszcze wciśnięte


W ramach mojego głównego oddziału zrobiłem git merge some-other-branch lokalnie, ale nigdy nie pchnął zmian do wzorca początkowego. Nie chciałem się scalić, więc chciałbym to cofnąć. Kiedy robisz git status po moim scaleniu otrzymałem tę wiadomość:

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

Na podstawie niektórych instrukcje, które znalazłemPróbowałem uciekać

git revert HEAD -m 1

ale teraz otrzymuję tę wiadomość git status:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

Nie chcę, aby mój oddział był wyprzedzany przez dowolną liczbę zatwierdzeń. Jak wrócić do tego punktu?


3088
2018-03-05 19:24


pochodzenie


Jeśli chcesz zachować historię, innymi słowy, jest jakaś zmiana, którą ktokolwiek kiedykolwiek wyciągnął od ciebie, lub gdzieś ją popchnął, użyj rozwiązania w odpowiedzi Jurija Uszakowa poniżej! - Sedrik
Proszę odznacz bieżącą wygrywającą odpowiedź, jest niebezpieczna (jak wielu wskazano), ale wciąż zbiera głosy. Dla mnie "MBO" wygląda najlepiej, chociaż ma o wiele mniej punktów. - inger
Jeśli potrzebujesz zachować historię, posługiwać się Yurirozwiązanie poniżej! (wystarczy dodać link do komentarza @Sedrik) - cregox
Związane z: Powróć do poprzedniego zatwierdzenia Git.
To świetny zasób prosto z Githuba: Jak cofnąć (prawie) wszystko za pomocą Gita - jasonleonhard


Odpowiedzi:


Z git reflog sprawdź, który commit jest wcześniejszy przed scaleniem (git reflog będzie lepszym rozwiązaniem niż log git). Następnie możesz je zresetować za pomocą:

git reset --hard commit_sha

Jest jeszcze inny sposób

git reset --hard HEAD~1

dostaniesz z powrotem 1 commit.

Należy pamiętać, że wszelkie zmodyfikowane i niezatwierdzone / usunięte pliki zostaną zresetowane do stanu niezmienionego. Aby je zachować, zmień je lub zobacz --merge opcja poniżej.


Jak @Vmont sugerował poniżej w swojej odpowiedzi, w tym bezpośrednim przypadku używając:

git reset --hard ORIG_HEAD

może przynieść lepsze wyniki, ponieważ powinno zachować twoje zmiany. ORIG_HEAD będzie wskazywać na zatwierdzenie bezpośrednio przed wystąpieniem scalenia, więc nie musisz sam tego szukać.


Kolejną wskazówką jest użycie --merge przełącz zamiast --hard ponieważ nie powoduje niepotrzebnego resetowania plików:

--łączyć

Resetuje indeks i aktualizuje pliki w drzewie roboczym, które różnią się między <commit> i HEAD, ale zachowuje te, które różnią się między indeksem a drzewem roboczym (tj. Które mają zmiany, które nie zostały dodane).


3380
2018-03-05 19:34



Nie sądzę, żeby to działało (zawsze?) - "jeden przed scaleniem" będzie ostatnim zatwierdzeniem, które zostało połączone z drugim oddziałem - nie będzie to ostatnie zatwierdzenie w obecnym oddziale . Dobrze? (To może być po prostu wynikiem czego git log domyślnie wyświetla się - może jest inny wynik git log lub git reflog może być użyte do tego) - John Bachir
Sądzę, że to może zależeć od tego, czy zgniatamy połączenie. - Marcin Gil
@JohnBachir ma rację. w git log wyjście, chcesz spojrzeć na dwie nadrzędne zatwierdzenia. Jednym z nich jest ostatnie zatwierdzenie w twojej branży, jedno jest ostatnim zatwierdzeniem w oddziale, do którego się przyłączyłeś. Chcesz git reset --hard do nadrzędnego zatwierdzenia w oddziale, z którym się łączyłeś. - Justin
@JohnBachir: dopóki "scalenie" nie jest tak naprawdę szybkie do przodu, spowoduje to nowe zatwierdzenie, które znajduje się na górze dziennika, i to zatwierdzenie ma dwoje rodziców (lub więcej niż 2, jeśli robisz ośmiornicę łączyć). Jeśli usuniesz to jedno zatwierdzenie scalania, znikną również wszystkie starsze zatwierdzenia przychodzące z scalania. Aby być bezpiecznym, po zresetowaniu gita powie ci, gdzie jest nowa głowa: "HEAD jest teraz na 88a04de <commit message>". Zawsze patrzę na to, aby upewnić się, że trafiam tam, gdzie się spodziewałem. Mój projekt używa standardowego schematu nazewnictwa gałęzi, aby zachować niezapomniane wspomnienia. - Mark E. Haase
To, co uważałem za użyteczne, to przyjrzenie się "git reflog" i szukanie ostatniego zatwierdzenia, które zrobiłem w master. Następnie zrób git reset --hard <commit_sha> - Max Williams


Zakładając, że twój lokalny mistrz nie wyprzedził pochodzenia / mistrza, powinieneś być w stanie to zrobić

git reset --hard origin/master

Potem twój lokalny master gałąź powinna wyglądać identycznie origin/master.


1290
2018-03-17 18:06



@Carter to w rzeczywistości nie jest najlepszą odpowiedzią. Możliwe, że pochodzenie / mistrz może wyprzedzić lokalnego mistrza tuż przed scaleniem przez niektóre zatwierdzenia, w takim przypadku może to nie dać pożądanych rezultatów - Dhruva Sagar
@ dhruva-sagar Tak, ale dopóki git nie mówi, że jesteś z tyłu, a ty nie sprowadzasz, powinieneś być w porządku. - Kelvin
Dzięki! Jest to idealne, jeśli (i tylko jeśli) masz zdalne repozytorium. - tomc
Nie, nie jest idealny do tego pytania, zobacz klauzulę "założyć". Odpowiedź MBO faktycznie obejmuje ten przypadek oraz przypadek, w którym scalenie nie jest jedynym lokalnym zatwierdzeniem. - inger
Jeszcze raz, może to ostrzeżenie powinien przejść do samej odpowiedzi: Zawsze unikaj przepisywania historii git! - cregox


Widzieć rozdział 4 w książce Git i oryginalny post autorstwa Linusa Torvaldsa.

Aby cofnąć scalenie to już zostało zepchnięte:

git revert -m 1 commit_hash

Pamiętaj, aby przywrócić cofnięcie, jeśli ponownie wykonasz oddział, na przykład Linus.


1085
2018-06-02 16:31



^ - Jedyną poprawną odpowiedzią tutaj, jak przywrócić scalanie bez łamania historii. Jest to ważne, jeśli pracujesz z udostępnionym repozytorium. - Ruslan Kabalin
To nie zostało przegłosowane bardziej, ponieważ zmiana nigdy nie została zepchnięta, więc nie ma powodu, aby dodawać przypadkowe połączenie z historią. Wymaż ją lokalnie i przejdź dalej. - Justin
Odwracanie zatwierdzenia, które nie zostało pchnięte, wygląda brzydko w historii i czyni go bardziej zagmatwanym. Jeśli jeszcze go nie pchnąłeś, bardziej sensowne jest przesunięcie HEAD do tyłu o kilka razy, TO pchnięcie. - Mark E. Haase
"To nie zostało przegłosowane bardziej, ponieważ ..." - jednak, dla osób takich jak ja przychodzących na to pytanie, ponieważ my / popchnęliśmy dodatkowe zobowiązania, jest to nieocenione. - perfectionist
@perfectionist agreed :) Żałuję, że nie było sposobu na przeniesienie tej odpowiedzi na inne pytanie - (może jest?) - mikermcneil


Dziwne, że brakowało najprostszego polecenia. Większość odpowiedzi działa, ale cofnięcie scalenia właśnie wykonałeś, to jest łatwy i bezpieczny sposób:

git reset --merge ORIG_HEAD

W ref ORIG_HEAD wskaże oryginalne zatwierdzenie sprzed scalenia.

(The --merge opcja nie ma nic wspólnego z scalaniem. To po prostu git reset --hard ORIG_HEAD, ale bezpieczniejsze, ponieważ nie wpływa na niezatwierdzone zmiany.)


833
2018-01-29 15:46



Tak, to jest zdecydowanie najprostszy sposób. Zastanawiam się, dlaczego ma tak mało głosów w porównaniu z innymi odpowiedziami. - Pablo Olmos de Aguilera C.
Jeśli zabrudziłeś swoje drzewo robocze, git reset --merge ORIG_HEAD zachowuje te zmiany. - yingted
To jest odpowiedź dla mnie. Nie ma potrzeby git reflog albo coś innego. Dziękuję Ci. - crmpicco
Tak, najlepsza odpowiedź. Jest to przykład tego, jak system głosowania stackoverflow po prostu nagradza odpowiedzi, które są wysyłane wcześniej. - samthebest
Ta odpowiedź pojawiła się prawie trzy lata po przyjęciu; ale zgadzam się, to działało świetnie! - Mike Branski


W nowszych wersjach Git, jeśli jeszcze nie zatwierdziłeś scalenia i masz konflikt seryjnymożesz po prostu:

git merge --abort

Od man git merge:

[To] może być uruchomione tylko po konflikcie spowodowanym konfliktami. git merge --abort przerwie proces scalania i spróbuje zrekonstruować stan przed scaleniem.


307
2018-02-12 02:13





Powinieneś zresetować do poprzedniego zatwierdzenia. To powinno działać:

git reset --hard HEAD^

Lub nawet HEAD^^ aby przywrócić to zatwierdzenie. Zawsze możesz podać pełną referencję SHA, jeśli nie masz pewności, ile kroków należy podjąć.

Jeśli masz problemy, a Twój oddział główny nie ma żadnych zmian lokalnych, możesz zresetować do origin/master.


104
2018-03-05 19:31



Najlepsza odpowiedź IMHO, zawiera własny kod PO (przy założeniu tylko 1 kroku do przywrócenia, który wydawał się być w Q), jak również skrótu randomguy3 (który działa, gdy "twój oddział główny nie miał żadnych lokalnych zmian ") - inger
Całkowicie zgadzam się, że to najlepsza odpowiedź tutaj !!! - Konstantin
Czy komentatorzy, @Inger i @Konstantin, dlaczego? Przybyłeś tutaj po stworzeniu mojej odpowiedzi i jest to bardziej poprawne. Podejście do HEAD o jeden krok jest często błędne, a musielibyście policzyć, jak daleko zajdziecie. Git już gotowe ORIG_HEAD dla ciebie, dlaczego go nie użyć? - odinho - Velmont
czy zresetuje również lokalne zmiany? #Proszę zaktualizować. - CoDe
To działało idealnie dla mnie, resetowanie głowy w ten sposób ma dużo więcej sensu niż połowa odpowiedzi tutaj. - Varda Elentári


Ostatnio używałem git reflog aby w tym pomóc. Działa to głównie tylko wtedy, gdy nastąpiło scalenie JUST i było na twoim komputerze.

git reflog może zwrócić coś takiego:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

Pierwsza linia wskazuje, że nastąpiło scalenie. Druga linia to czas przed moim scaleniem. ja po prostu git reset --hard 43b6032 zmusić tę gałąź do śledzenia przed scaleniem i przeniesieniem.


78
2017-12-19 17:51



Omigosh ratuje życie :) - M.G.Palmer
O stary. Dziękuję bardzo. - Ross Henderson
Dlaczego nie jest to najlepsza odpowiedź, której nie znam. To działało idealnie. - Matt
Dziękuję za to, niesamowite! - zooblin


Dzięki nowoczesnemu Git możesz:

git merge --abort

Starsza składnia:

git reset --merge

Stara szkoła:

git reset --hard

Ale w rzeczywistości warto to zauważyć git merge --abort jest tylko równoważny git reset --merge jeśli się uwzględni MERGE_HEAD jest obecny. Można to odczytać w komendzie Git help for merge.

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

Po nieudanym scaleniu, gdy nie ma MERGE_HEAD, nieudane scalenie może zostać cofnięte git reset --merge, ale niekoniecznie z git merge --abort, więc są nie tylko starą i nową składnią tego samego.

Osobiście znajduję git reset --merge o wiele potężniejszy i przydatniejszy w codziennej pracy, więc to ta, której zawsze używam.


42
2018-05-08 19:13



Sprawdziło się doskonale dla mnie. Każdy inny post mówi, że jest to tak skomplikowane, ale zrobiło to dokładnie to, czego się oczekuje. Przypuszczam, że zadziałało tylko dlatego, że były konflikty, które nie odpowiadają dokładnie na pierwotne pytanie. - Jeremy
Ta odpowiedź nie koncentruje się na sytuacji PO i pozostawia ważny kontekst. - Ben Wheeler


W porządku, odpowiedzi, które otrzymałem od innych osób, były bliskie, ale nie zadziałały. Oto co zrobiłem.

Robiąc to...

git reset --hard HEAD^
git status

... dało mi następujący status.

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

Musiałem wtedy wpisać to samo git reset komendę jeszcze kilka razy. Za każdym razem, gdy to robiłem, wiadomość zmieniła się o jedną, jak widać poniżej.

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

W tym momencie zobaczyłem komunikat o stanie zmieniony, więc próbowałem zrobić git pulli wydawało się, że działa:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

Tak krótka historia, moje polecenia sprowadzają się do tego:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull

32
2018-03-05 19:54



lub mógłbyś użyć HEAD^^^^ - hasen
może nawet zresetować do origin/master ;) - hasen
Łał! to działało! - Yiğit Güler