Cofnij scalenie Git, które nie zostało jeszcze wypchnięte

3941

W mojej gałęzi master zrobiłem git merge some-other-branchlokalnie, ale nigdy nie wysłałem zmian do master master. Nie chciałem się połączyć, więc chciałbym to cofnąć. Po git statusscaleniu otrzymałem ten komunikat:

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

Na podstawie niektórych instrukcji, które znalazłem , próbowałem uruchomić

git revert HEAD -m 1

ale teraz otrzymuję ten komunikat z git status:

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

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

Matt Huggins
źródło
3
Jeśli chcesz zachować historię, innymi słowy, istnieje zmiana, którą ktoś kiedykolwiek od ciebie wyciągnął lub gdzieś ją zepchnąłeś, skorzystaj z rozwiązania w odpowiedzi Jurija Uszakowa poniżej!
Sedrik,
6
Usuń zaznaczenie aktualnej zwycięskiej odpowiedzi, jest niebezpieczna (jak wielu zauważyło), ale wciąż zbiera głosy. Dla mnie „MBO” wygląda najlepiej, choć ma o wiele mniej punktów.
inger
5
Jeśli chcesz zachować historię , skorzystaj z rozwiązania Yuri poniżej ! (tylko dodanie linku do komentarza @Sedrik)
cregox 17.09.13
3
To świetny zasób prosto z Github: Jak cofnąć (prawie) cokolwiek z Gitem
jasonleonhard

Odpowiedzi:

4454

Z git reflogczeku, który popełnił jeden przed scalanie ( git reflogbędzie lepszym rozwiązaniem niż git log). Następnie możesz go zresetować za pomocą:

git reset --hard commit_sha

Jest też inny sposób:

git reset --hard HEAD~1

Otrzymasz z powrotem 1 zatwierdzenie.

Należy pamiętać, że wszelkie zmodyfikowane i niezaangażowane / niezasadzone pliki zostaną przywrócone do stanu niezmodyfikowanego . Aby je ukryć, ukryj zmiany lub zobacz --mergeopcję poniżej.


Jak @Velmont zasugerował poniżej w swojej odpowiedzi, w tym bezpośrednim przypadku przy użyciu:

git reset --hard ORIG_HEAD

może przynieść lepsze wyniki, ponieważ powinien zachować twoje zmiany. ORIG_HEADwskaże zatwierdzenie bezpośrednio przed wystąpieniem scalenia, więc nie musisz sam go szukać.


Kolejną wskazówką jest użycie --mergeprzełącznika zamiast, --hardponieważ nie resetuje niepotrzebnie plików:

git reset --merge ORIG_HEAD

--łą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 zawierają zmiany, które nie zostały dodane).

Marcin Gil
źródło
129
Nie sądzę, aby to (zawsze?) Działało - „jeden przed scaleniem” będzie ostatnim zatwierdzeniem, które zostało scalone z drugiego oddziału - nie będzie ostatnim zatwierdzeniem w bieżącym oddziale . Dobrze? (Może to wynikać z tego, co git logdomyślnie wyświetla się - być może jest inny wynik git loglub git reflogmoże być do tego użyty)
John Bachir
6
Myślę, że to może zależeć od tego, czy zgniatasz scalenie.
Marcin Gil
29
@JohnBachir ma rację. W git logwyniku chcesz spojrzeć na dwa zatwierdzenia nadrzędne. Jeden to najnowsze zatwierdzenie w oddziale, jeden to ostatnie zatwierdzenie w oddziale, w którym się połączyłeś. Chcesz, aby git reset --hardrodzic zatwierdził oddział, w którym się połączyłeś.
Justin,
7
@JohnBachir: Dopóki „scalenie” nie jest tak naprawdę szybkim przewijaniem do przodu, spowoduje to nowe zatwierdzenie, które znajduje się na początku dziennika, a to zatwierdzenie ma dwoje rodziców (lub więcej niż 2, jeśli wykonasz ośmiornicę) łączyć). Jeśli usuniesz to zatwierdzenie jednego scalania, znikną również wszystkie starsze zatwierdzenia, które przyszły ze scalenia. Jednak dla bezpieczeństwa, po resecie git powie ci, gdzie jest nowa głowa: „HEAD jest teraz pod 88a04de <komunikat zatwierdzenia>”. Zawsze patrzę na to, aby upewnić się, że skończyłem tam, gdzie się spodziewałem. Mój projekt używa standardowego schematu nazewnictwa gałęzi, aby zachować niezapomniane wrażenia.
Mark E. Haase,
44
Przydało mi się spojrzenie na „git reflog” i poszukiwanie ostatniego zatwierdzenia, które zrobiłem w master. Następnie zróbgit reset --hard <commit_sha>
Max Williams
1455

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

git reset --hard origin/master

Wówczas lokalny masteroddział powinien wyglądać identycznie origin/master.

randomguy3
źródło
71
@Carter to nie jest najlepsza odpowiedź. Możliwe, że pochodzenie / master może wyprzedzać lokalnego mistrza tuż przed scaleniem przez niektóre commity, w takim przypadku może to nie dać pożądanych rezultatów
Dhruva Sagar
15
@ dhruva-sagar Tak, ale dopóki git nie mówi, że jesteś z tyłu, a ty nie przynosisz, wszystko powinno być w porządku.
Kelvin
3
Dzięki! Jest to idealne, jeśli (i tylko jeśli) masz zdalne repozytorium.
tomc
2
Nie, nie jest to idealne rozwiązanie dla tego pytania, patrz klauzula „zakładaj”. Odpowiedź MBO faktycznie obejmuje ten przypadek, a przypadek, w którym scalenie nie jest jedynym zatwierdzeniem lokalnym.
inger
2
Jeszcze raz, może to ostrzeżenie powinno przejść do samej odpowiedzi: Zawsze unikaj przepisywania historii git!
cregox,
1175

Zobacz rozdział 4 w książce Git i oryginalny post Linusa Torvaldsa .

Aby cofnąć scalenie, które zostało już wypchnięte :

git revert -m 1 commit_hash

Pamiętaj, aby cofnąć wycofanie, jeśli ponownie popełniasz oddział, jak powiedział Linus.

Jurij Geinish
źródło
10
@perfectionist zgodził się :) Żałuję, że nie było sposobu na przeniesienie tej odpowiedzi na inne pytanie - (może jest?)
mikermcneil 16.04.2013
Aby uzyskać więcej informacji na temat
wycofania
1
Aby mieć pewność, że to przywrócenie zadziałało, możesz wykonać polecenie git diff hash1 hash2, gdzie hash1 to zatwierdzone przywrócenie, a hash2 to stare zatwierdzenie, do którego stanu chciałeś wrócić. Brak wyników == sukces! Byłem w stanie cofnąć wiele zatwierdzeń, wykonując to wiele razy, zaczynając od cofnięcia najnowszego scalenia i pracy wstecz. git diff pokazał mi, że skończyłem w pożądanym przeze mnie stanie.
Robert Sinton
6
Zauważ, że to tak naprawdę nie rozwiązuje pytania oryginalnego plakatu . Oryginalny plakat już wykorzystany git revert -m 1 <commit>. Problem polega na tym, że zrobienie tego nie kasuje przypadkowego scalenia, które zrobił (i jeszcze nie pchnął). Inne odpowiedzi dotyczące twardego resetu są lepsze w przypadku problemu z oryginalnym plakatem.
To świetny zasób prosto z Github: Jak cofnąć (prawie) cokolwiek z Gitem
jasonleonhard
986

Dziwne, że brakowało najprostszego polecenia. Większość odpowiedzi działa, ale cofając właśnie wykonane połączenie, jest to prosty i bezpieczny sposób :

git reset --merge ORIG_HEAD

Referencja ORIG_HEADwskaże pierwotne zatwierdzenie sprzed scalenia.

(Ta --mergeopcja nie ma nic wspólnego ze scaleniem. Jest po prostu git reset --hard ORIG_HEADbezpieczniejsza, ponieważ nie dotyka niezatwierdzonych zmian.)

odinho - Velmont
źródło
17
Jeśli odtąd wyczyściłeś działające drzewo, git reset --merge ORIG_HEADzachowaj te zmiany.
Yingted
1
To jedyna poprawna odpowiedź (nie mówię, że to najlepsza odpowiedź - zauważ różnicę). Powiedzmy, na master, zrobiłem 3 zatwierdzenia w t1, t3 i t5. Powiedzmy, że na gałęzi 1 zrobiłem 3 komentarze na t2, t4 i t6 (zakładając, że t1, t2, t3, t4, t5 i t6 są w porządku chronologicznym). Każde polecenie podobne do git reset --hard HEAD~5resetuje tylko HEAD (może usunąć zatwierdzenia zarówno w master, jak i branch1). Tylko --mergeopcja usuwa merge.
Manu Manjunath,
@Manu --mergeOpcja tak naprawdę nie usuwa scalenia, możesz go użyć --hard, będzie również działał dobrze. Jest to wskazówka ORIG_HEAD, która jest wskazówką tutaj, jest ustalana przed wykonaniem scalenia z miejscem, w którym stoisz w tym momencie. :)
odinho
@ zastanawiał się, co rozumiesz przez „Jeśli odtąd zabrudziłeś działające drzewo, git reset --merge ORIG_HEAD zachowuje te zmiany”. Czy chodziło Ci o zmianę plików po scaleniu? W każdym razie połączyłem, a potem rozwiązałem konflikty. Ale potem chciałem zresetować scalanie i zrobiłem zgodnie z instrukcją w tej odpowiedzi. Wszystko było w porządku i nie zachowało moich zmian dokonanych po scaleniu. Moje lokalne repozytorium jest po prostu podobne do stanowiska, zanim dokonałem fuzji.
Samitha Chathuranga,
git reset --hard ORIG_HEADPolecenie działało idealnie dla mnie - to może być wspomagane przez fakt, że nie dokonywała innych zmian w repozytorium po lokalny git mergestarałem się cofnąć. Polecenie po prostu resetuje stan repozytorium z powrotem do stanu sprzed scalenia. Dzięki za świetną radę!
bluebinary
391

W nowszych wersjach Git, jeśli jeszcze nie dokonałeś scalania i masz konflikt scalania , możesz po prostu:

git merge --abort

Od man git merge:

[To] można uruchomić tylko wtedy, gdy scalenie spowodowało konflikty. git merge --abortprzerwie proces scalania i spróbuje odtworzyć stan sprzed scalenia.

Travis Reeder
źródło
8
Jego scalenie zostało popełnione, ale nie zostało wypchnięte (patrz tytuł), on już się scalił, twoje polecenie działa tylko wtedy, gdy wciąż jest w trakcie scalania
JBoy
135

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

git reset --hard HEAD^

Lub nawet HEAD^^cofnąć zatwierdzenie przywrócenia. Zawsze możesz podać pełne odniesienie do SHA, jeśli nie jesteś pewien, ile kroków wstecz powinieneś zrobić.

W przypadku problemów i braku zmian lokalnych w oddziale głównym, możesz zresetować do origin/master.

MBO
źródło
5
Najlepsza odpowiedź IMHO, obejmuje własną OP (zakładając tylko 1 krok do cofnięcia, co wydawało się być w Q), a także skrót shortguy3 (który działa, gdy „twoja gałąź główna nie miała żadnych lokalnych zmian ")
Inger
4
Komentatorzy, @Inger i @Konstantin, dlaczego? Przybyłeś tutaj po utworzeniu mojej odpowiedzi, która jest bardziej poprawna. Samo przejście do HEAD jeden krok jest często złe i trzeba by liczyć, jak daleko trzeba się posunąć. Git już ORIG_HEADdla ciebie ustawia , czemu by tego nie użyć?
odinho
czy zresetuje również lokalne zmiany? #Proszę zaktualizować.
CoDe
Działa to dla mnie idealnie, zresetowanie takiej głowy ma o wiele więcej sensu niż połowa odpowiedzi tutaj.
Varda Elentári
HEAD ^ równa się zatwierdzeniu przed HEAD? i ^^ czy dwa zatwierdzenia są wcześniejsze? Zgadywanie, że to nie zadziała przy szybkich połączeniach do przodu?
Marcus Leon
87

Ostatnio używałem git reflogdo tego pomocy. 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

Pierwszy wiersz wskazuje, że nastąpiło scalenie. Druga linia to czas przed moim połączeniem. Po prostu git reset --hard 43b6032zmuszam tę gałąź do śledzenia przed scaleniem i kontynuowania.

Parris
źródło
Świetna odpowiedź, dziękuję! Musiałem cofnąć scalenie, ale inne odpowiedzi tylko pomieszały go, wykorzystując reflogdo uzyskania SHA i przekazania go do git resetdziałania.
Lankymart
51

Dzięki nowoczesnemu Git możesz:

git merge --abort

Starsza składnia:

git reset --merge

Stara szkoła:

git reset --hard

Ale tak naprawdę warto zauważyć, że git merge --abortjest to odpowiednik tylko git reset --mergetego, co MERGE_HEADjest obecne. Można to odczytać w pomocy Git dotyczącej polecenia scalania.

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

Po nieudanym scaleniu, gdy nie ma MERGE_HEAD, nieudanego scalenia można cofnąć git reset --merge, ale niekoniecznie za pomocą git merge --abort, więc są one nie tylko starą i nową składnią tego samego .

Osobiście uważam, że jest o git reset --mergewiele bardziej wydajny i użyteczny w codziennej pracy, więc tego zawsze używam.

Martin G.
źródło
Działa świetnie dla mnie. Co drugi post mówi, że jest to tak skomplikowane, ale zrobiło to dokładnie to, czego oczekiwano. Przypuszczam, że zadziałało tylko dlatego, że były konflikty, które nie odpowiadają dokładnie pierwotnemu pytaniu.
Jeremy,
Ta odpowiedź nie koncentruje się na sytuacji PO i pomija ważny kontekst.
Ben Wheeler,
37

Dobra, odpowiedzi udzielone mi przez inne osoby były bliskie, ale to nie zadziałało. Oto co zrobiłem.

Robiąc to...

git reset --hard HEAD^
git status

... dał 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.

Potem musiałem git resetjeszcze kilka razy wpisać to samo polecenie. Za każdym razem, gdy to robiłem, wiadomość zmieniał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, że komunikat o statusie się zmienił, więc spróbowałem zrobić git pull, a to wydawało się 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ótko mówiąc, moje polecenia sprowadzały się do tego:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
Matt Huggins
źródło
19
lub mogłeś użyćHEAD^^^^
hasen
17
może nawet zresetować do origin/master;)
hasen
23

Możesz użyć, git reflogaby znaleźć poprzednią kasę. Czasami jest to dobry stan, do którego chcesz wrócić.

Konkretnie,

$ git reflog
$ git reset --hard HEAD@{0}
stephjang
źródło
1
Dziękuję Ci! Zaoszczędziłeś pół dnia mojej pracy. Nie mogłem jednak wyjść z trybu ponownego logowania za pomocą żadnego polecenia.
Katarzyna
1
@Katarzyna użyj klawisza „q”, aby wyjść z
reflogu
21

Jeśli jesteś w trakcie łączenia, zawsze możesz go przerwać git merge --abort

llioor
źródło
2
dzięki stary i ja miałem zamiar zrobić to straszne rzeczy poprawną odpowiedź. na szczęście przewinąłem w dół. Chcę tylko usunąć głowę scalania
Nyuu,
15

Byłem w stanie rozwiązać ten problem za pomocą jednego polecenia, które nie wymaga wyszukiwania identyfikatora zatwierdzenia.

git reset --hard remotes/origin/HEAD

Przyjęta odpowiedź nie działała dla mnie, ale to polecenie osiągnęło wyniki, których szukałem.

Ralph Ritoch
źródło
Dokładnie! Resetuje twoje zmiany do HEAD oddziału! Nie robić jeden po drugim
Carlos Zinato,
nie działało dla mnie. w rzeczywistości odesłał lokalny oddział z powrotem miesiąc lub dwa. Na szczęście jest to wszystko lokalne, więc zawsze mogę zniszczyć gałąź i pobrać ją ponownie. Chciałem tylko wskazać to na wypadek, gdyby inni próbowali tego.
Matt Pengelly,
@MattPengelly ta metoda jest w dużej mierze nieudokumentowana i zwykle działa, jeśli twoja gałąź jest zsynchronizowana ze zdalną gałęzią przed scaleniem. Czy minęły miesiące, odkąd Twój oddział był zsynchronizowany ze zdalnym oddziałem?
Ralph Ritoch
@MattPengelly zależy również od gałęzi, na którą wskazuje HEAD. Korzystam z gitflow w jednym z moich projektów i chociaż jestem w gałęzi deweloperskiej, piloty / origin / HEAD są wskazywane na origin / master, więc gdybym musiał cofnąć scalenie, prawdopodobnie musiałbym zresetować do pilotów / origin / develop
Ralph Ritoch
14

Jeśli jeszcze tego nie zrobiłeś, możesz tylko użyć

$ git checkout -f

Cofnie scalenie (i wszystko, co zrobiłeś).

Idealmind
źródło
Próbowałem tego i faktycznie zwiększyło liczbę zatwierdzeń, które wyprzedza mój lokalny oddział.
barclay,
14

Przeszedłem do tego pytania, również chcąc przywrócić dopasowanie do źródła (tj. NO zatwierdza przed początkiem). Dalsze badania wykazały, że istnieje resetpolecenie, które dokładnie to:

git reset --hard @{u}

Uwaga: @{u}jest skrótem od origin/master. (I oczywiście potrzebujesz tego zdalnego repozytorium, aby to działało).

leanne
źródło
14

Musisz zmienić HEAD, oczywiście nie twoja HEAD ....

Więc zanim odpowiemy, dodajmy trochę tła, wyjaśniając, co to jest HEAD.

First of all what is HEAD?

HEADjest po prostu odniesieniem do bieżącego zatwierdzenia (najnowszego) w bieżącej gałęzi.
W HEADdanym momencie może być tylko jeden . (nie liczącgit worktree )

Zawartość HEADjest przechowywana w środku .git/HEADi zawiera 40 bajtów SHA-1 bieżącego zatwierdzenia.


detached HEAD

Jeśli nie korzystasz z ostatniego zatwierdzenia, co oznacza, że HEADnazywa się to wcześniejszym zatwierdzeniem w historii detached HEAD.

wprowadź opis zdjęcia tutaj

W wierszu polecenia będzie to wyglądało tak: SHA-1 zamiast nazwy gałęzi, ponieważ HEADnie wskazuje ona końca wierzchołka bieżącej gałęzi

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Kilka opcji odzyskiwania po odłączeniu HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Spowoduje to pobranie nowej gałęzi wskazującej żądany zatwierdzenie.
To polecenie pobierze do danego zatwierdzenia.
W tym momencie możesz utworzyć gałąź i od tego momentu zacząć pracować.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Zawsze możesz również użyć reflog.
git reflogwyświetli każdą zmianę, która zaktualizowała HEADi sprawdzenie żądanego wpisu ponownego logowania spowoduje HEADpowrót do tego zatwierdzenia.

Za każdym razem, gdy HEAD zostanie zmodyfikowany, pojawi się nowy wpis w reflog

git reflog
git checkout HEAD@{...}

Spowoduje to powrót do żądanego zatwierdzenia

wprowadź opis zdjęcia tutaj


git reset --hard <commit_id>

„Przenieś” HEAD z powrotem do żądanego zatwierdzenia.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Uwaga: ( od wersji Git 2.7 )
    możesz również korzystać z nich git rebase --no-autostash.

git revert <sha-1>

„Cofnij” podany zakres zatwierdzania lub zatwierdzania.
Polecenie reset spowoduje „cofnięcie” wszelkich zmian dokonanych w danym zatwierdzeniu.
Nowe zatwierdzenie z łatką cofania zostanie zatwierdzone, podczas gdy oryginalne zatwierdzenie pozostanie również w historii.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ten schemat ilustruje, które polecenie robi co.
Jak widać, reset && checkoutzmodyfikuj HEAD.

wprowadź opis zdjęcia tutaj

CodeWizard
źródło
To jest skarb 🐱‍👤🐱‍👤🐱‍👤
Jawand Singh
12

Najprostsza odpowiedź jest udzielona przez odinho - Velmont

Najpierw zrób git reset --merge ORIG_HEAD

Dla tych, którzy chcą zresetować po wprowadzeniu zmian, zrób to (ponieważ jest to pierwszy post widziany w przypadku pytań dotyczących scalania resetowania git)

git push origin HEAD --force

Spowoduje to zresetowanie w taki sposób, że po ściągnięciu nie otrzymasz ponownie scalonych zmian.

Harsha
źródło
10

Tylko dla dodatkowej opcji do obejrzenia, głównie podążałem za modelem rozgałęziania opisanym tutaj: http://nvie.com/posts/a-successful-git-branching-model/ i jako taki połączyłem się z --no-ff(nie przewijanie do przodu) zwykle.

Właśnie przeczytałem tę stronę, ponieważ przypadkowo połączyłem gałąź testową zamiast gałęzi wydania z masterem do wdrożenia (strona internetowa, master jest tym, co jest na żywo). W gałęzi testowej połączono dwie inne gałęzie, których suma wynosi około sześć zatwierdzeń.

Tak więc, aby cofnąć całe zatwierdzenie, potrzebowałem tylko jednego git reset --hard HEAD^i to odwróciło całe scalenie. Ponieważ połączenia nie zostały szybko przekazane, scalenie było blokiem, a jeden krok wstecz to „gałąź nie scalona”.

Damien Byrne
źródło
10

Możesz użyć tylko dwóch poleceń, aby cofnąć scalenie lub zrestartować przez określone zatwierdzenie:

  1. git reset --hard commitHash (powinieneś użyć zatwierdzenia, które chcesz zrestartować, np. 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (Wysyłanie nowego lokalnego oddziału głównego do źródła / wzorca)

Powodzenia i śmiało!

Matheus Abreu
źródło
10

Można to zrobić na wiele sposobów.

1) Przerwij scalanie

Jeśli znajdujesz się pomiędzy złym scaleniem (błędnie zrobionym z niewłaściwą gałęzią) i chciałeś uniknąć scalenia, aby wrócić do gałęzi najpóźniej jak poniżej:

git merge --abort

2) Zresetuj HEAD do zdalnej gałęzi

Jeśli pracujesz ze zdalnej gałęzi rozwoju, możesz zresetować HEAD do ostatniego zatwierdzenia na zdalnej gałęzi, jak poniżej:

git reset --hard origin/develop

3) Usuń bieżącą gałąź i ponownie dokonaj płatności ze zdalnego repozytorium

Biorąc pod uwagę, że pracujesz nad rozwojem oddziału w lokalnym repozytorium, który synchronizuje się ze zdalnym / develop oddziału, możesz wykonać następujące czynności:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop
Amit Kaneria
źródło
że „1) Przerwij łączenie” było wystarczające. Upvoting.
CodeToLife
1
Bądź ostrożny! git merge --abort "można uruchomić tylko wtedy, gdy scalenie spowodowało konflikty. git merge --abort przerwie proces scalania i spróbuje odtworzyć stan sprzed scalenia"
Pedro García Medina
8

Jeśli twoje scalenie i odpowiednie zatwierdzenia nie zostały jeszcze wypchnięte, zawsze możesz przełączyć się na inną gałąź, usunąć oryginalną i ponownie ją utworzyć.

Na przykład przypadkowo połączyłem gałąź rozwoju w master i chciałem to cofnąć. Wykonując następujące kroki:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! Mistrz jest na tym samym etapie, co pochodzenie, a twój źle połączony stan zostaje skasowany.

Stephan
źródło
1
Uwaga: To nie tylko cofnie scalanie, ale także wszelkie lokalne zatwierdzenia, które zostały dokonane od ostatniego push to origin.
Martijn Heemels
4

Jeśli chcesz skorzystać z rozwiązania wiersza polecenia, sugeruję skorzystanie z odpowiedzi MBO.

Jeśli jesteś nowicjuszem, możesz polubić podejście graficzne:

  1. Rozpocznij gitk(z linii poleceń lub kliknij prawym przyciskiem myszy w przeglądarce plików, jeśli ją masz)
  2. Możesz łatwo zauważyć tam zatwierdzenie scalania - pierwszy węzeł od góry z dwójką rodziców
  3. Kliknij link do pierwszego / lewego rodzica (ten w bieżącym oddziale przed scaleniem, zwykle dla mnie czerwony)
  4. Na wybranym zatwierdzeniu kliknij prawym przyciskiem myszy „Resetuj gałąź do tutaj”, wybierz tam twardy reset
Inger
źródło
4

Strategia: Utwórz nowy oddział, z którego wszystko będzie dobrze.

Uzasadnienie: Cofnięcie scalenia jest trudne. Istnieje zbyt wiele rozwiązań, w zależności od wielu czynników, takich jak to, czy dokonałeś lub przeforsowałeś scalenie, czy też od czasu scalenia pojawiły się nowe zatwierdzenia. Ponadto nadal musisz mieć dość głębokie zrozumienie git, aby dostosować te rozwiązania do swojej sprawy. Jeśli ślepo zastosujesz się do instrukcji, możesz skończyć z „pustym połączeniem”, w którym nic nie zostanie scalone, a kolejne próby scalenia sprawią, że Git powie ci „Już aktualne”.

Rozwiązanie:

Powiedzmy, że chcesz połączyć devsię feature-1.

  1. Znajdź wersję, która ma zostać scalona:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Sprawdź to (cofnij się w czasie):

    git checkout e5f6g7h8
    
  3. Utwórz nowy oddział stamtąd i sprawdź:

    git checkout -b feature-1
    

Teraz możesz ponownie uruchomić scalanie:

  1. Łączyć: git merge dev

  2. Napraw konflikty scalania.

  3. Popełnić: git commit

  4. Gdy wyniki będą satysfakcjonujące, usuń starą gałąź: git branch --delete feature-1

pyb
źródło
2

Wystarczy utworzyć nowy oddział, a następnie wybrać do niego pożądane zatwierdzenia.

Jego oszczędzanie i prostota resetuje opisane w wielu odpowiedziach powyżej

devi
źródło
1
Zgadzam się z tą sugestią, szczególnie jeśli nie czujesz się dobrze z wymienionymi poleceniami git. Może to być wolniejsze z większym „trudem”, ale jeśli nie pojawia się zbyt wiele i martwisz się utratą pracy, warto spróbować.
Greg
1

Myślę, że możesz zrobić, git rebase -i [hash] [branch_name] gdzie [hash]jest skrót identyfikujący dla tego, jak daleko wstecz chcesz przewinąć plus jeden (lub wiele cofnięć, które chcesz przejść), a następnie usunąć wiersze dla zatwierdzeń w edytorze, których już nie chcesz . Zapisz plik. Wyjście. Modlić się. I powinno być przewinięte. Być może będziesz musiał zrobić git reset --hard, ale w tym momencie powinno być dobrze. Możesz także użyć tego do wyciągnięcia określonych zatwierdzeń ze stosu, jeśli nie chcesz zachować ich w swojej historii, ale może to pozostawić repozytorium w stanie, którego prawdopodobnie nie chcesz.

tychoish
źródło
1

Jeśli dokonałeś scalenia:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
dorycki
źródło
1
  1. Najpierw upewnij się, że wszystko popełniłeś.

  2. Następnie zresetuj repozytorium do poprzedniego stanu roboczego:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    lub używając --hard( spowoduje to usunięcie wszystkich lokalnych, niezatwierdzonych zmian! ):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    Użyj skrótu, który był tam przed nieprawidłowo połączonym zatwierdzeniem.

  3. Sprawdź, które zatwierdzenia chcesz ponownie zatwierdzić w poprzedniej poprawnej wersji, wykonując:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Zastosuj swoje właściwe zatwierdzenia w górnej części właściwej wersji repozytorium przez:

    • Za pomocą cherry-pick (zmiany wprowadzone przez niektóre istniejące commity)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Lub przez wybranie zakresu zatwierdzeń przez:

      • Najpierw sprawdź poprawne zmiany przed ich scaleniem:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • Najpierw sprawdź poprawne zmiany przed ich scaleniem:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        gdzie jest to zakres poprawnych zatwierdzeń, które popełniłeś (z wyjątkiem błędnie popełnionego scalenia).

kenorb
źródło
1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

To działało dla mnie .. !!

Siva Kumar
źródło
0

Jeśli zauważysz, że trzeba przywrócić natychmiast po scaleniu i nie zrobili niczego innego po próbie scalenia, wystarczy wydać polecenie: git reset --hard HEAD@{1}.

Zasadniczo twoje scalenie shabędzie wskazywać, HEAD@{0}czy nic więcej nie zostało popełnione po scaleniu, podobnie HEAD@{1}jak poprzedni punkt przed scaleniem.

Dut A.
źródło
0

Najprostsza z najprostszych szans, znacznie prostsza niż cokolwiek tu powiedziane:

Usuń oddział lokalny (lokalny, nie zdalny) i pociągnij go ponownie. W ten sposób cofniesz zmiany w gałęzi master i na każdego wpłynie zmiana, której nie chcesz forsować. Zacznij od nowa.

Luis
źródło
0

W takim przypadku będziesz chciał zresetować swój oddział git reset --hard <branch_name>. Jeśli chcesz zapisać zmiany przed ich zresetowaniem, pamiętaj o utworzeniu nowego oddziału i git checkout <branch_name>.

Możesz również zresetować stan do konkretnego zatwierdzenia za pomocą git reset --hard <commit_id>.

Jeśli zmiany zostały wprowadzone, możesz użyć git revert <branch_name>zamiast tego. Koniecznie sprawdź, jak używać git revert i git checkout w innych scenariuszach.

Nesha Zoric
źródło