Git wypycha na niewłaściwą gałąź

99

Pracując z git, po kilku „commitach” i kilku „push”, zdałem sobie sprawę, że używam złej gałęzi!

Teraz muszę w jakiś sposób usunąć moje zmiany w evil_branch i zatwierdzić i wypchnąć zmiany w right_branch

Jaki jest najlepszy (i prosty) sposób na zrobienie tego?

Dziękuję Ci

Alessandro De Simone
źródło
Dobre pytanie @tokland: 99% programistów ruby ​​używa git, a projekt, nad którym pracuję, jest w RoR ... ale wiem, że to nie może być dobra motywacja
Alessandro De Simone
3
Z mojego punktu widzenia nie jest to duplikat tego, co zauważył Halfdan, ponieważ chodzi również o przeniesienie commits do innej gałęzi, a nie tylko ich usunięcie.
olenz

Odpowiedzi:

144

przełącz się na tę gałąź, sprawdź git logi git revertte zatwierdzenia indywidualnie. Gdy już to zrobisz, przełącz się z powrotem do żądanej gałęzi i tam możesz użyć git cherry-pickdo wybrania określonych zatwierdzeń z git refs i scalenia go z odpowiednią gałęzią.

git checkout wrong_branch
git revert commitsha1
git revert commitsha2
git checkout right_branch
git cherry-pick commitsha1
git cherry-pick commitsha2

Jeśli zatwierdzenia są zgrupowane razem i nie ma żadnych zatwierdzeń wypychanych po twoich brudnych zatwierdzeniach, możesz nawet użyć git resettej złej gałęzi do stanu tuż przed zatwierdzeniami, a następnie wykonać to ponownie, używając, git cherry-pickaby umieścić swoje zatwierdzenia we właściwej gałęzi.

git checkout wrong_branch
git reset commitsha3 #commit just before commitsha2
git checkout right_branch
git cherry-pick commitsha1
git cherry-pick commitsha2
Dhruva Sagar
źródło
Revert + cherry-pick wydaje się dużo prostsze niż inne możliwe metody obejmujące resetowanie głowy i / lub ponowne ustawienie.
ChrisV,
2
W przypadku git cherry-pick możesz umieścić wiele shasów w jednej linii, tj git cherry-pick commitsha1 commitsha2.
Thomas W
Ratownik! I nie jest skomplikowane. Dziękuję Ci!
Craig Silver,
co się dzieje, gdy chcesz połączyć nieprawidłową gałąź (np. rozwijać) w prawą_ gałąź (np. funkcja / X), a następnie otrzymujesz cofnięcia
cofające
revertjest o wiele czystszy i mniej dramatyczny niż wtedy reset, gdy naprawdę chcesz usunąć coś wrażliwego (poświadczenia?)
Qumber
3

Najprostszym sposobem jest użycie git rebase. Załóżmy, że masz takie ustawienie:

A -- B -- C -- C1 -- C2 # right branch
          \
           \-- D -- C3 -- C4 # wrong branch

Chcesz przenieść zmianę C3, C4 do prawej gałęzi.

git checkout -b new_wrong_branch D
git checkout wrong_branch
git rebase D --onto right_branch
git checkout right_branch
git merge right_branch wrong_branch
git branch -d wrong_branch
git branch rename new_wrong_branch wrong_branch

Teraz jest to ustawienie

A -- B -- C -- C1 -- C2 -- C3 -- C4 # right_branch
          \
           \ -- D # wrong_branch

Następnie musisz siłą pchać swoje wyniki (JEŚLI nikt jeszcze nie zsynchronizował się ze zdalnym repozytorium):

git push -f remote:right_branch
Olivier Verdier
źródło
Nie próbowałem tego rozwiązania, już wypracowałem pierwszą odpowiedź (i zadziałało). Nie pomyślałem o rebase, wygląda to na dobrą alternatywę, dziękuję
Alessandro De Simone
1
Zamiast git push -flepszego wykorzystania git push --force-with-lease. Przynajmniej zapewnia to, że zdalne odniesienie będzie aktualizowane tylko wtedy, gdy nikt nie włożył innych zatwierdzeń do twoich zatwierdzeń.
Pierre-Olivier Vares
2

Trochę skrótu do odpowiedzi Dhruvy

git checkout wrong_branch
git revert commitsha1

git checkout right_branch
git push right_branch

git checkout wrong_branch
git reset commitsha2 #commit just before commitsha1
git push wrong_branch -f
tarikakyol
źródło