Wiem, że przepisywanie historii jest złe, yada yada.
Ale jak trwale usunąć kilka zatwierdzeń ze zdalnego oddziału?
Wiem, że przepisywanie historii jest złe, yada yada.
Ale jak trwale usunąć kilka zatwierdzeń ze zdalnego oddziału?
Odpowiedzi:
Jesteś git reset --hardoddziałem lokalnym, aby usunąć zmiany z działającego drzewa i indeksu, a git push --forceTwój zmieniony oddział lokalny do pilota. ( inne rozwiązanie tutaj , obejmujące usunięcie zdalnej gałęzi i ponowne jej przekazanie)
Ta SO odpowiedź ilustruje niebezpieczeństwo takiego polecenia, szczególnie jeśli ludzie polegają na odległej historii swoich lokalnych repozytoriów.
Musisz być przygotowany, aby wskazać ludziom do wychodzenie z UPSTREAM rebase części git rebasestrony man
Z Git 2.23 (sierpień 2019, dziewięć lat później) użyjesz nowego polecenia git switch.
To znaczy:
(zastąp liczbą zatwierdzeń do usunięcia)git switch -C mybranch origin/mybranch~nn
To przywróci indeks i działające drzewo, tak jak git reset --hardzrobiłby to.
push --forcewyjeździe
git gcnie zawsze jest uruchamiana wystarczająco często po stronie zdalnej. Na przykład na GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
Pamiętaj tylko, aby użyć last_working_commit_id, gdy cofasz niedziałający zatwierdzenie
git reset --hard <last_working_commit_id>
Nie możemy więc zresetować tego commit_id, czego nie chcemy.
W takim razie musimy przesłać do zdalnej gałęzi:
git push --force
git reset --hardpowinno zrobić.
W tym samouczku pokazano trzy opcje . W przypadku zerwania linku zostawię tutaj główne kroki.
1 Cofnij pełne zatwierdzenie
git revert dd61ab23
2 Usuń ostatni zatwierdzenie
git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>
lub, jeśli oddział jest dostępny lokalnie
git reset HEAD^ --hard
git push <<remote>> -f
gdzie + dd61 ... jest twoim hashem zatwierdzającym, a git interpretuje x ^ jako element nadrzędny x, a + jako wymuszone nie-fastforwared push.
3 Usuń zatwierdzenie z listy
git rebase -i dd61ab23^
Otworzy się i edytor pokaże listę wszystkich zatwierdzeń. Usuń ten, którego chcesz się pozbyć. Ukończ bazę i wciśnij siłę, aby wykonać repo.
git rebase --continue
git push <remote_repo> <remote_branch> -f
Jeśli chcesz usunąć na przykład ostatnie 3zatwierdzenia, uruchom następujące polecenie, aby usunąć zmiany z systemu plików (drzewa roboczego) i zatwierdzić historię (indeks) w lokalnym oddziale:
git reset --hard HEAD~3
Następnie uruchom następujące polecenie (na komputerze lokalnym), aby zmusić zdalny oddział do przepisania historii:
git push --force
Gratulacje! Wszystko gotowe!
Niektóre uwagi:
Możesz pobrać żądany identyfikator zatwierdzenia, uruchamiając
git log
Następnie można wymienić HEAD~Nw <desired-commit-id>ten sposób:
git reset --hard <desired-commit-id>
Jeśli chcesz zachować zmiany w systemie plików i po prostu zmodyfikować indeks (historię zatwierdzeń), użyj --softflagi jak git reset --soft HEAD~3. Następnie masz szansę sprawdzić najnowsze zmiany i zachować lub upuścić wszystkie lub ich części. W drugim przypadku runnig git statuspokazuje pliki zmienione od tego czasu <desired-commit-id>. Jeśli użyjesz --hardopcji, git statuspowie ci, że twój oddział lokalny jest dokładnie taki sam jak oddział zdalny. Jeśli nie używasz --hardani --soft, używany jest tryb domyślny --mixed. W tym trybie git help resetmówi:
Resetuje indeks, ale nie działające drzewo (tzn. Zmienione pliki są zachowane, ale nie są oznaczone do zatwierdzenia) i zgłasza, co nie zostało zaktualizowane.
To może być za mało za późno, ale pomogła mi fajnie brzmiąca opcja „nuklearna”. Zasadniczo za pomocą polecenia filter-branchmożesz usunąć pliki lub zmienić coś w dużej liczbie plików w całej historii git.
Najlepiej to wyjaśniono tutaj .
Uproszczenie z odpowiedzi pctroll, podobnie na podstawie tego postu na blogu .
# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote
Czasami najłatwiejszym sposobem rozwiązania tego problemu jest utworzenie nowej gałęzi z miejsca, w którym wiesz, że kod jest dobry. Następnie możesz zostawić błędną historię oddziału w spokoju, na wypadek, gdybyś musiał później wybrać inne zatwierdzenia. Zapewnia to również, że nie straciłeś historii zatwierdzeń.
Z lokalnego oddziału, który popełnił błąd:
git log
skopiuj skrót zatwierdzenia, w którym chcesz, aby gałąź była w, i zamknij dziennik git
git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch
Teraz masz nowy oddział tak, jak chcesz.
Jeśli potrzebujesz również zachować konkretne zatwierdzenie z błędnego oddziału, którego nie ma w nowym oddziale, możesz po prostu wybrać konkretny zatwierdzenie, którego potrzebujesz:
git checkout the_errant_branch
git log
Skopiuj skrót zatwierdzenia jednego zatwierdzenia, którego potrzebujesz, aby pobrać do dobrej gałęzi i zamknąć dziennik git.
git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied
Poklep się po plecach.