Git pull po wymuszonej aktualizacji


332

Właśnie zmiażdżyłem niektóre zobowiązania git rebasei zrobiłem git push --force(co jest złe, wiem).

Teraz inni inżynierowie oprogramowania mają inną historię, a kiedy to zrobią git pull, Git się połączy. Czy istnieje sposób, aby to naprawić, z wyjątkiem robienia rm my-repo; git clone git@example.org:my-repo.git?

Potrzebuję czegoś przeciwnego git push --force, ale git pull --forcenie dał zamierzonych rezultatów.


16
mogą usunąć swój oddział i ponownie go utworzyć, bez konieczności usuwania całego repozytorium:git checkout master && git branch -D test && git checkout -b test origin/test
— Florian Klein


Odpowiedzi:


509

Aby otrzymać nowe zobowiązania

git fetch

Resetowanie

Możesz zresetować zatwierdzenie dla lokalnego oddziału za pomocą git reset.

Aby zmienić zatwierdzenie oddziału lokalnego:

git reset origin/master --hard

Bądź jednak ostrożny, jak to dokumentuje:

Resetuje indeks i działające drzewo. Wszelkie zmiany w śledzonych plikach w działającym drzewie od czasu <commit> są odrzucane.

Jeśli chcesz zachować wszystkie zmiany, które wprowadziłeś lokalnie - --softzamiast tego wykonaj reset. Który zaktualizuje historię zatwierdzeń dla gałęzi, ale nie zmieni żadnych plików w katalogu roboczym (a następnie możesz je zatwierdzić).

Rebase

Możesz odtworzyć swoje lokalne zatwierdzenia na dowolnym innym zatwierdzeniu / oddziale, używając git rebase:

git rebase -i origin/master

Spowoduje to wywołanie rebase w trybie interaktywnym, w którym możesz wybrać sposób zastosowania każdego indywidualnego zatwierdzenia, którego nie ma w historii, której aktualizujesz.

Jeśli zatwierdzenia, które usunąłeś (za pomocą git push -f), zostały już wprowadzone do historii lokalnej, zostaną wymienione na liście jako zatwierdzenia, które zostaną ponownie zastosowane - będą musiały zostać usunięte w ramach bazy lub po prostu zostaną ponownie włączone do historii dla oddziału - i pojawi się w odległej historii przy kolejnym wypychaniu.

Skorzystaj z pomocy, git command --helpaby uzyskać więcej informacji i przykładów na temat dowolnego z powyższych (lub innych) poleceń.


2
@iblue wybiera między utratą wszystkich zmian, usunięciem historii zatwierdzeń, ale zachowaniem zmian w plikach, lub próbą zastosowania każdego zatwierdzenia nad nową nagłówkiem. Najprostszą opcją jest prawdopodobnie miękki reset.
— AD7six

1
@iblue Kiedy twój kolega użyje polecenia `git reabse origin / master 'i znaczy, że wcześniej mieli już pewne zatwierdzenie, git zapisze twoje zatwierdzenie z tyłu ich zatwierdzenia.
— Tim

6
Warto wspomnieć, że jeśli dotyczy to innej gałęzi:git reset origin/otherbranch --hard
— bmaupin

Tak więc, w celu wyjaśnienia, jest to albo : Opcja 1: reset --hard, lub Opcja 2: reset --soft+ rebase, prawda?
— PlasmaBinturong

2
@PlasmaBinturong No. git reset --soft origin/masterzmieni historię zatwierdzania, aby dopasować zdalne i różnice etapów do zdalnego, które następnie zostaną zatwierdzone . W tym scenariuszu nie byłoby potrzeby dokonywania zmian w bazie (i byłoby to niemożliwe z powodu niezatwierdzonych zmian), ponieważ nie ma różnicy w historii zatwierdzeń. Dwie opcje są resetowane lub rebase - nie kombinacja obu. Proszę zadać pytanie, czy twój scenariusz jest inny niż ten, na który tu odpowiedziałem.
— AD7six

16

Nie naprawi to gałęzi, które już zawierają kod, którego nie chcesz (zobacz poniżej, jak to zrobić), ale jeśli wyciągnęły jakąś gałąź i teraz chcą, aby była czysta (a nie „wyprzedzająca” przed origin / some-branch), a następnie:

git checkout some-branch   # where some-branch can be replaced by any other branch
git branch base-branch -D  # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch  # recreating branch with correct commits

Uwaga: Możesz połączyć je wszystkie, umieszczając && między nimi

Uwaga 2: Florian wspomniał o tym w komentarzu, ale kto czyta komentarze, gdy szuka odpowiedzi?

Uwaga 3: Jeśli masz zanieczyszczone gałęzie, możesz utworzyć nowe na podstawie nowej „głupiej gałęzi” i po prostu zatwierdzić wybór.

Dawny:

git checkout feature-old  # some branch with the extra commits
git log                   # gives commits (write down the id of the ones you want)
git checkout base-branch  # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd   # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch

Teraz nowa funkcja jest twoją gałęzią bez dodatkowych (prawdopodobnie złych) zmian!


Tego naprawdę chciałem. Ktoś zmienił gałąź główną (na bóg wie, z jakiego powodu), ale nie miałem żadnych lokalnych zmian, które chciałbym zatwierdzić lub coś w tym rodzaju. Więc wszystko, co musiałem zrobić, to usunąć moją lokalną gałąź master (co wydawało się naprawdę dziwne) i zrobić ponownie kasę. Dzięki!
— Danilo Carvalho

@ Peter-Mortensen Zmiany powinny być znaczące zgodnie z stackoverflow.com/help/editing
— Tom Prats

dla ostatniego kroku możesz także użyć git checkout -b base-branch origin/base-branchzgit checkout --track origin/base-branch
— bluesmonk

1

Pociągnij za pomocą podstawy

Regularne pobieranie to fetch + merge, ale to, czego chcesz, to fetch + rebase. Jest to opcja z pullpoleceniem:

git pull --rebase

Używam tego przez cały czas, aby pobrać najnowszy kod z mastera do mojej gałęzi funkcji, bez tych wszystkich zatwierdzeń scalania w historii.
— herman
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.