Niedawno pisałem na blogu na ten temat:
W jaki sposób aktualizujemy tę gałąź funkcji? Scalanie najnowszych zatwierdzeń nadrzędnych jest łatwe, ale chcesz uniknąć tworzenia zatwierdzeń scalających, ponieważ nie zostaną one docenione po wypchnięciu ich do wyższego poziomu: wtedy efektywnie ponownie zatwierdzasz zmiany nadrzędne, a te zatwierdzenia nadrzędne otrzymają nowy skrót ( gdy mają nowego rodzica). Jest to szczególnie ważne, ponieważ te scalone zatwierdzenia zostaną odzwierciedlone w żądaniu ściągnięcia GitHub, gdy wypchniesz te aktualizacje do swojej osobistej gałęzi funkcji GitHub (nawet jeśli zrobisz to po wydaniu żądania ściągnięcia).
Dlatego musimy zmienić bazę zamiast scalać:
git co devel #devel is ansible's HEAD aka "master" branch
git pull --rebase upstream devel
git co user-non-unique
git rebase devel
Zarówno opcja rebase, jak i polecenie rebase do git utrzymają twoje drzewo w czystości i unikną scalania zatwierdzeń. Pamiętaj jednak, że są to twoje pierwsze zatwierdzenia (z którymi wydałeś pierwsze żądanie ściągnięcia), które są ponownie bazowane i które mają teraz nowy skrót zatwierdzenia, który różni się od oryginalnych skrótów, które nadal znajdują się w zdalnej gałęzi repozytorium github .
Teraz wypychanie tych aktualizacji do twojej osobistej gałęzi funkcji GitHub zakończy się niepowodzeniem, ponieważ obie gałęzie się różnią: lokalne drzewo gałęzi i zdalne drzewo gałęzi są „niezsynchronizowane” z powodu tych różnych skrótów zatwierdzania. Git powie ci najpierw git pull --rebase
, a potem pchnij ponownie, ale nie będzie to proste szybkie pchnięcie do przodu, ponieważ twoja historia została przepisana. Nie rób tego!
Problem polega na tym, że ponownie pobrałbyś swoje pierwsze zmienione zatwierdzenia, tak jak były pierwotnie, a te zostaną scalone na górze twojego lokalnego oddziału. Ze względu na stan niezsynchronizowania to ściąganie nie jest stosowane w sposób czysty. Otrzymasz zepsutą historię, w której twoje zatwierdzenia pojawiają się dwa razy. Kiedy wrzucisz to wszystko do gałęzi funkcji GitHub, zmiany te zostaną odzwierciedlone w pierwotnym żądaniu ściągnięcia, które stanie się bardzo, bardzo brzydkie.
AFAIK, tak naprawdę nie ma na to całkowicie czystego rozwiązania. Najlepszym rozwiązaniem, jakie znalazłem, jest wymuszenie wypchnięcia lokalnego oddziału do oddziału GitHub (w rzeczywistości wymuszenie aktualizacji bez przewijania do przodu):
Zgodnie z git-push (1):
Update the origin repository’s remote branch with local branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling in the origin repository.
Więc nie ciągnij, po prostu pchaj siłą w ten sposób:
git push svg +user-non-unique
lub:
git push svg user-non-unique --force
To faktycznie po prostu nadpisze twój zdalny oddział, ze wszystkim w twoim lokalnym oddziale. Zatwierdzenia, które znajdują się w zdalnym strumieniu (i spowodowały awarię) pozostaną tam, ale będą wiszącymi zatwierdzeniami, które ostatecznie zostaną usunięte przez git-gc (1). Nie ma sprawy.
Jak powiedziałem, jest to AFAICS najczystsze rozwiązanie. Wadą tego jest to, że twój PR zostanie zaktualizowany o te najnowsze commity, które otrzymają późniejszą datę i mogą pojawić się niezsynchronizowane w historii komentarzy do PR. Nie ma dużego problemu, ale może być mylące.