Jak usunąć nieprzesłane zatwierdzenia git?

947

Przypadkowo zaangażowałem się w niewłaściwy oddział. Jak usunąć to zatwierdzenie?

NullVoxPopuli
źródło

Odpowiedzi:

1807

Usuń ostatni zatwierdzenie, zachowując pracę, którą wykonałeś:

git reset --soft HEAD~1

Usuń ostatni zatwierdzenie, niszcząc pracę, którą wykonałeś:

git reset --hard HEAD~1
dbyrne
źródło
13
upewnij się, że HEAD wskazuje na oddział .. (sprawdź to najpierw)
Frank Schwieterman
128
I upewnij się, że HEAD ~ 1 jest zatwierdzeniem ... Możesz także zrobićgit reset --hard origin
Daenyth,
13
Myśl git remotepochodzenie list do mnie git reset --hard originmówi fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Dlaczego?
trss
7
To jest niesamowite. Właśnie uratowałem mi życie.
NinjaBoy,
2
git reset HEAD~1zachowa również wszystkie zmiany, ale pozostawi pusty indeks zamiast zachować wszystko (tak jak --softopcja).
Holloway,
138

Zastanawiam się, dlaczego najlepszą odpowiedzią, jaką znalazłem, są tylko komentarze! ( autor: Daenyth z 86 głosami )

git reset --hard origin

To polecenie zsynchronizuje lokalne repozytorium ze zdalnym repozytorium, pozbywając się wszystkich zmian, które wprowadziłeś w swoim lokalnym. Możesz także wykonać następujące czynności, aby pobrać dokładną gałąź, którą masz w źródle.

git reset --hard origin/<branch>
Ashkan Sirous
źródło
16
Dzięki za to, nieco rozszerzając wyjaśnienie: dla konkretnej gałęzi:git reset --hard origin/<branch>
wyczyść
4
Lub git reset --soft origin/<branch>, jeśli chcesz pozbyć się zatwierdzenia, ale zachowaj lokalną pracę.
konik rzeczny
1
Rozumiem fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., musisz podać gałąź jak:git reset --hard origin/feature/my-cool-stuff
Kip
Znakomity! To faktycznie działa, w przeciwieństwie do „zaakceptowanej” odpowiedzi, która po prostu odrywa głowę i pozostawia cię zawieszonego.
mae
55

Nie usuwaj go: wystarczy jeden zatwierdzenie git cherry-pick.

Ale jeśli miałeś kilka zatwierdzeń na niewłaściwej gałęzi, to właśnie tam git rebase --ontoświeci:

Załóżmy, że masz to:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, możesz zaznaczyć masteri przenieść go tam, gdzie chcesz:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, zresetuj gałąź, gdzie powinna być:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

, i na koniec przenieś swoje commity (zastosuj je ponownie, tworząc faktycznie nowe commity)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch
VonC
źródło
nie to nie było pytanie.
KatariaA
1
@KatariaA Jest to ważna alternatywa dla usunięcia zatwierdzenia dokonanego w niewłaściwym oddziale i pomoże innym w tej samej sytuacji (dobre zatwierdzenie wykonane w niewłaściwym oddziale).
VCC
14

Wykonaj a git rebase -i FAR_ENOUGH_BACKi upuść linię dla zatwierdzenia, którego nie chcesz.

Hank Gay
źródło
6

Jeśli chcesz przenieść ten zatwierdzenie do innej gałęzi, uzyskaj SHA danego zatwierdzenia

git rev-parse HEAD

Następnie przełącz bieżącą gałąź

git checkout other-branch

I cherry-pickzobowiązanie doother-branch

git cherry-pick <sha-of-the-commit>
Alexander Groß
źródło
Z mojego doświadczenia wynika, że ​​nie powoduje to cofnięcia zatwierdzenia z oryginalnej gałęzi, a zatem wymaga git reset --hard HEAD~1późniejszego. Myślę, że użycie reset --softprzełączania gałęzi i ponowne zatwierdzenie zaoszczędziłoby dodatkowej pracy. Z drugiej strony korzystałem z SourceTree do wykonywania większości moich podstawowych czynności, tylko z linijką poleceń po tym, jak popełniłem błąd.
jusopi
3

W celach informacyjnych uważam, że można „wyciąć” zatwierdzenia z bieżącej gałęzi nie tylko za pomocą git reset --hard, ale także za pomocą następującego polecenia:

git checkout -B <branch-name> <SHA>

W rzeczywistości, jeśli nie zależy ci na wyewidencjonowaniu, możesz ustawić oddział na cokolwiek zechcesz za pomocą:

git branch -f <branch-name> <SHA>

Byłby to programowy sposób usuwania commits z gałęzi, na przykład w celu skopiowania do niej nowych commits (przy użyciu rebase).

Załóżmy, że masz gałąź, która jest odłączona od systemu głównego, ponieważ wziąłeś źródła z innej lokalizacji i zrzuciłeś ją do gałęzi.

Masz teraz gałąź, w której wprowadziłeś zmiany, nazwijmy to „tematem”.

Teraz utworzysz duplikat gałęzi tematu, a następnie zmienisz jej bazę na zrzut kodu źródłowego, który znajduje się w gałęzi „zrzut”:

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Teraz twoje zmiany są ponownie stosowane w gałęzi topic_duplicate na podstawie punktu początkowego „zrzutu”, ale tylko zatwierdzenia, które nastąpiły od czasu „master”. Więc twoje zmiany od czasu master są teraz ponownie stosowane na „dump”, ale wynik kończy się na „topic_duplicate”.

Następnie możesz zamienić „zrzut” na „temat_duplikacja”, wykonując:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Lub z

git branch -M topic_duplicate dump

Lub po prostu odrzucając zrzut

git branch -D dump

Być może możesz po prostu wyczyścić plik po wyczyszczeniu bieżącego „topic_duplicate”.

Co próbuję powiedzieć to to, że jeśli chcesz zaktualizować obecny „duplikat” oddział w oparciu off innego przodka trzeba najpierw usunąć poprzednio „cherrypicked” zobowiązuje wykonując git reset --hard <last-commit-to-retain>lub git branch -f topic_duplicate <last-commit-to-retain>a następnie kopiując innych zobowiązuje się (z głównym gałąź tematyczna) przez zmianę lub wybieranie.

Zmiana zasad działa tylko w gałęzi, która ma już zatwierdzenia, więc musisz zduplikować gałąź tematu za każdym razem, gdy chcesz to zrobić.

Wybieranie Cherry jest znacznie łatwiejsze:

git cherry-pick master..topic

Tak więc cała sekwencja sprowadza się do:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Po sprawdzeniu gałęzi z duplikatem tematu. Spowoduje to usunięcie wcześniej wybranych pobrań z bieżącego duplikatu i ponowne zastosowanie wszystkich zmian zachodzących w „temacie” nad bieżącym „zrzutem” (innego przodka). Wydaje się to dość wygodnym sposobem na oparcie rozwoju na „prawdziwym” głównym serwerze nadrzędnym, przy użyciu innego „głównego” serwera nadrzędnego, aby sprawdzić, czy zmiany lokalne również dotyczą tego. Alternatywnie możesz po prostu wygenerować różnicę, a następnie zastosować ją poza dowolnym drzewem źródłowym Git. Ale w ten sposób możesz zachować aktualną zmodyfikowaną (łataną) wersję, która jest oparta na wersji twojej dystrybucji, podczas gdy twój rzeczywisty rozwój jest przeciwko prawdziwemu masterowi.

Aby tylko zademonstrować:

  • reset spowoduje, że twoja gałąź wskaże inne zatwierdzenie (--hard również sprawdza poprzednie zatwierdzenie, --soft zachowuje dodane pliki w indeksie (które zostałyby zatwierdzone, jeśli zatwierdzisz ponownie), a domyślne (--mixed) nie będzie sprawdź poprzednie zatwierdzenie (czyszczenie lokalnych zmian), ale wyczyści indeks (nic nie zostało jeszcze dodane do zatwierdzenia)
  • możesz po prostu zmusić gałąź do wskazania innego zatwierdzenia
  • możesz to zrobić, jednocześnie od razu sprawdzając to zatwierdzenie
  • rebasing działa na commits obecnych w bieżącym oddziale
  • kompletowanie oznacza kopiowanie z innej gałęzi

Mam nadzieję, że to komuś pomoże. Chciałem to przepisać, ale nie mogę teraz. Pozdrowienia.

Xennex81
źródło
0

Po wydaniu polecenia zadziałało dla mnie, wszystkie zatwierdzone zmiany lokalne są usuwane, a ustawienia lokalne są resetowane do tego samego co zdalne źródło / gałąź główna.

git reset - twarde pochodzenie

Atul Sureka
źródło