Cofnij określone zatwierdzenie w Git, które zostało przekazane do zdalnych repozytoriów

788

Jaki jest najprostszy sposób cofnięcia konkretnego zatwierdzenia, który jest:

  • nie w głowie ani w głowie
  • Został przekazany do pilota.

Ponieważ jeśli nie jest to ostatni zatwierdzenie,

git reset HEAD

nie działa A ponieważ został przekazany do pilota,

git rebase -i

i

git rebase --onto

spowoduje jakiś problem w pilotach.

Co więcej, nie chcę tak naprawdę modyfikować historii. Jeśli był zły kod, był w historii i można go zobaczyć. Po prostu chcę, żeby to było w kopii roboczej i nie mam nic przeciwko zatwierdzeniu przez scalanie w odwrotnej kolejności.

Innymi słowy, jaki jest odpowiednik Git następujących poleceń svn:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

który usuwa wszystkie zmiany z 295 do 302 poprzez odwrotne scalenie wszystkich zmian w tych wersjach, jako nowe zatwierdzenie.

svn merge -c -302 ^/trunk

który anuluje zatwierdzenie 302, oczywiście przez dodanie kolejnego zatwierdzenia, które odwraca scala zmiany z tego odpowiedniego zatwierdzenia.

Pomyślałem, że powinna to być dość prosta operacja w Git i dość powszechny przypadek użycia. Jaki jeszcze sens mają atomowe zmiany?

Mamy ukrywanie sceniczne i wszystko po to, aby upewnić się, że zatwierdzenia są całkowicie atomowe, czy nie powinieneś być w stanie łatwo cofnąć jednego lub więcej z tych zatwierdzeń atomowych?

Lakshman Prasad
źródło

Odpowiedzi:

1210

Zidentyfikuj skrót zatwierdzenia, używając git log, a następnie użyj, git revert <commit>aby utworzyć nowe zatwierdzenie, które usuwa te zmiany. W pewnym sensie git revertjest odwrotnie git cherry-pick- ten drugi stosuje łatkę do gałęzi, która jej brakuje, pierwsza usuwa ją z gałęzi, która ją ma.

Andrew Aylett
źródło
237
I użyj przełącznika -n, jeśli chcesz odzyskać kod, ale nie zostanie on automatycznie
zatwierdzony
17
Do czego służy opcja „m”? Próbowałem git przywrócić 8213f7d, ale dostałem to zamiast tego: błąd: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 to scalenie, ale nie podano opcji -m. fatal: przywrócenie nie powiodło się
Malcolm
10
Aby cofnąć scalenie: git revert -m 1 <hash>
brunozrk
31
Ostrzeżenie dla każdego, kto chce cofnąć scalenie: git revert cofnie wszystkie zmiany danych (tzn. Zmiany w plikach zostaną cofnięte), ale scalanie nadal pozostaje w historii. Z tego powodu, jeśli spróbujesz ponownie scalić tę samą gałąź później, nie będzie ona zawierać żadnych zatwierdzeń z gałęzi scalającej przed cofniętym scaleniem. To najprawdopodobniej nie to, czego chcesz. Aby ponownie w pełni scalić gałąź, musisz najpierw cofnąć zatwierdzenie w miejscu, w którym cofnąłeś oryginalne scalenie. Dowiedz się więcej tutaj: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/…
etreworgy
3
Link w komentarzu @etreworgy to 404. Podejrzewam, że jest to aktualna wersja linku: kernel.org/pub/software/scm/git/docs/howto/…
Tim Smith
368

Nie podoba mi się funkcja automatycznego zatwierdzania git revert, więc może to być pomocne dla niektórych.

Jeśli chcesz tylko zmodyfikować pliki, a nie automatyczne zatwierdzanie , możesz użyć--no-commit

% git revert --no-commit <commit hash>

który jest taki sam jak -n

% git revert -n <commit hash>
Dziękuję Ci
źródło
9
Możesz także zrobić, git reset HEAD~1 --softjeśli już się wycofałeś-n
Daniel
1
Ale git reset HEAD~nnie rozwiąże cofania żadnego zatwierdzenia, które nie jest stale dostępne z głowy. Zapytanie polega na przywróceniu określonego zatwierdzenia.
sangeethkumarp
Użyłem tego rozwiązania, ale natrafiłem na konflikt w trakcie cofania. Po rozwiązaniu konfliktu postąpiłem git revert --continuezgodnie z instrukcją. Działało, ale niestety popełniło wyniki. Być może musiałem to zrobić git revert --no-commit --continue.
mareoraft
1
@sangeethkumarp komentarz Daniela to dodatkowy krok, który możesz zrobić po git revert, jeśli zapomniałeś -n; ponieważ w tym momencie ostatnim zatwierdzeniem jest cofnięcie, więc miękki reset cofnie to zatwierdzenie, ale nie związane z nim zmiany kodu przywrócenia
Oliver
@Daniel zapewnił rozwiązania za pomocą komentarza, działaj dla mnie Dziękuję bardzo 'git reset HEAD ~ 1 --soft' '
Md. Abu Sayed
41

Ponieważ został już wypchnięty, nie powinieneś bezpośrednio manipulować historią. git revertprzywróci określone zmiany z zatwierdzenia przy użyciu nowego zatwierdzenia, aby nie manipulować historią zatwierdzeń.

fosaPylon
źródło
1

Jeśli zatwierdzenie, które chcesz cofnąć, jest zatwierdzeniem scalonym (zostało już scalone), powinieneś wybrać jedną z opcji -m 1lub -m 2opcję, jak pokazano poniżej. Dzięki temu git dowie się, który nadrzędny zatwierdzony ze scalonego zatwierdzenia użyć. Więcej informacji można znaleźć TUTAJ .

  • git revert <commit> -m 1
  • git revert <commit> -m 2
Meysam Sadeghi
źródło