Jeśli naciśniesz commit do serwera, a następnie przepisać że popełniania lokalnie (z git reset
, git rebase
, git filter-branch
lub jakiejkolwiek innej manipulacji historii), a następnie popchnął że przepisany popełnić powrotem do serwera, można zepsuć nikogo, kto pociągnął. Oto przykład; powiedz, że popełniłeś A i wypchnąłeś go na serwer.
- * - * - A <- master
- * - * - A <- początek / wzorzec
Teraz decydujesz się przepisać A w sposób, o którym wspomniałeś, resetując i ponownie zatwierdzając. Zauważ, że pozostawia to wiszące zatwierdzenie, A, które ostatecznie zostanie zebrane jako śmieci, ponieważ nie jest osiągalne.
-*-*-ZA
\
A '<- mistrz
- * - * - A <- początek / wzorzec
Jeśli ktoś inny, powiedzmy Fred, ściągnie master
serwer z serwera, kiedy to robisz, będzie miał odniesienie do A, od którego może zacząć pracę:
- * - * - A '<- master
- * - * - A <- początek / wzorzec
- * - * - AB <- fred / master
Teraz, gdybyś był w stanie popchnąć swoje A 'do początku / końca, co spowodowałoby szybkie przewijanie do przodu, nie miałoby ono A w swojej historii. Więc jeśli Fred spróbuje ponownie pociągnąć, musiałby nagle scalić i ponownie wprowadzić zatwierdzenie A:
- * - * - A '<- master
- * - * - A <- początek / wzorzec
- * - * - AB- \
\ * <- fred / master
ZA'--/
Jeśli Fred zdarzy się, że to zauważy, może wykonać rebase, co uniemożliwi ponowne pojawienie się zatwierdzenia A. Ale musiałby to zauważyć i pamiętać, żeby to zrobić; a jeśli masz więcej niż jedną osobę, która ściągnęła A, wszyscy musieliby zmienić bazę, aby uniknąć dodatkowego zatwierdzenia A w drzewie.
Więc generalnie nie jest dobrym pomysłem zmienianie historii w repozytorium, z którego korzystają inni ludzie. Jeśli jednak wiesz, że nikt inny nie wyciąga z tego repozytorium (na przykład jest to twoje własne prywatne repozytorium lub masz tylko jednego programistę pracującego nad projektem, z którym możesz łatwo koordynować), możesz wymusić aktualizacja poprzez uruchomienie:
git push -f
lub
git push origin +master
Obaj zignorują sprawdzanie, czy nie ma szybkiego przewijania do przodu, i zaktualizują zawartość serwera do nowej wersji A ', porzucając wersję A, aby ostatecznie została usunięta.
Możliwe, że wymuszenie wypychania jest całkowicie wyłączone za pomocą receive.denyNonFastForwards
opcji konfiguracji. Ta opcja jest domyślnie włączona w repozytoriach współdzielonych. W takim przypadku, jeśli naprawdę chcesz wymusić wypychanie, najlepszą opcją jest usunięcie gałęzi i ponowne utworzenie jej za pomocą git push origin :master; git push origin master:master
. Jednak denyNonFastForwards
opcja jest włączona nie bez powodu, który opisano powyżej; na współdzielonym repozytorium oznacza to, że teraz każdy, kto go używa, musi upewnić się, że bazuje na nowej historii.
W repozytorium współużytkowanym generalnie lepiej jest po prostu wypchnąć nowe zatwierdzenia, które naprawią każdy problem; możesz użyć git revert
do wygenerowania zatwierdzeń, które cofną zmiany poprzednich zatwierdzeń.