Znam niektóre osoby, które używają git pull --rebase
domyślnie, i inne, które nalegają, aby nigdy ich nie używać. Wydaje mi się, że rozumiem różnicę między łączeniem a ponownym przetwarzaniem, ale staram się umieścić to w kontekście git pull
. Czy chodzi tylko o to, że nie chce się wyświetlać wielu komunikatów zatwierdzania scalania, czy są też inne problemy?
806
Odpowiedzi:
Powinieneś użyć
git pull --rebase
kiedyRzeczywiście - dlaczego więc nie? Jest to bardziej jasne i nie narzuca logicznego grupowania twoich zobowiązań.
Ok, chyba wymaga wyjaśnienia. W Git, jak zapewne wiesz, zachęca się do rozgałęziania i łączenia. Twój oddział lokalny, do którego ściągasz zmiany, i oddział zdalny to w rzeczywistości różne oddziały i
git pull
chodzi o ich scalenie. Jest to rozsądne, ponieważ nie naciskasz zbyt często i zwykle gromadzisz szereg zmian, zanim utworzą one ukończoną funkcję.Czasami jednak - z jakiegokolwiek powodu - wydaje ci się, że byłoby lepiej, gdyby te dwa - odległe i lokalne - były jedną gałęzią. Jak w SVN. To tutaj
git pull --rebase
wchodzi w grę. Nie łączysz się już - faktycznie zatwierdzasz na oddziale zdalnym . Właśnie o to chodzi.To, czy jest to niebezpieczne, czy nie, jest kwestią tego, czy traktujesz lokalny i zdalny oddział jako jedną nierozerwalną rzecz. Czasami jest to uzasadnione (gdy twoje zmiany są niewielkie lub jeśli jesteś na początku solidnego rozwoju, gdy ważne zmiany są wprowadzane przez małe zmiany). Czasami tak nie jest (kiedy normalnie tworzysz inną gałąź, ale jesteś zbyt leniwy, aby to zrobić). Ale to inne pytanie.
źródło
git config --global pull.rebase preserve
(zachowaj, oprócz włączenia zmiany, mówi, aby próbować zachować scalenia, jeśli dokonałeś tego lokalnie).Chciałbym przedstawić inną perspektywę tego, co tak naprawdę oznacza „git pull --rebase”, ponieważ wydaje się, że czasami się gubi.
Jeśli kiedykolwiek korzystałeś z Subversion (lub CVS), możesz być przyzwyczajony do zachowania „svn update”. Jeśli masz zmiany do zatwierdzenia, a zatwierdzenie nie powiedzie się, ponieważ zmiany zostały wprowadzone wcześniej, „svn update”. Subversion przechodzi przez scalenie wcześniejszych zmian z twoimi, potencjalnie powodując konflikty.
To, co właśnie zrobił Subversion, było zasadniczo „pull -rebase”. Przeformułowanie lokalnych zmian w stosunku do nowszej wersji jest częścią „zmiany”. Jeśli zrobiłeś „svn diff” przed nieudaną próbą zatwierdzenia, a następnie porównujesz wynikowy diff z wyjściem „svn diff” później, różnica między tymi dwoma różnicami jest tym, co zrobiła operacja zmiany wartości.
Główną różnicą między Git i Subversion w tym przypadku jest to, że w Subversion „twoje” zmiany istnieją tylko jako niezaangażowane zmiany w kopii roboczej, podczas gdy w Git masz faktyczne zatwierdzenia lokalnie. Innymi słowy, w Git rozwinęliście historię; Twoja historia i historia górna są rozbieżne, ale masz wspólnego przodka.
Moim zdaniem, w normalnym przypadku posiadania lokalnego oddziału po prostu odzwierciedla upstream oddział i robi na nim ciągły rozwój, właściwą rzeczą do zrobienia jest zawsze „--rebase”, bo to jest to, czego semantycznie faktycznie robi . Ty i inni wyrywacie się z zamierzonej liniowej historii oddziału. Fakt, że ktoś inny naciskał nieco przed twoją próbą pchnięcia, jest nieistotny i wydaje się, że każdy taki przypadek pomiaru czasu przynosi efekt przeciwny do skutku, łącząc się w historii.
Jeśli z jakiegoś powodu odczuwasz potrzebę bycia filią, jest to inna sprawa. Ale chyba, że masz konkretne i aktywne pragnienie przedstawienia swoich zmian w formie scalenia, moim zdaniem domyślne zachowanie powinno brzmieć „git pull --rebase”.
Rozważ inne osoby, które muszą obserwować i rozumieć historię Twojego projektu. Czy chcesz, aby historia była zaśmiecona setkami połączeń w całym miejscu, czy może chcesz tylko kilka wybranych połączeń, które reprezentują prawdziwe połączenia celowych rozbieżnych wysiłków rozwojowych?
źródło
git config --global branch.autosetupmerge always
?Być może najlepszym sposobem na wyjaśnienie tego jest przykład:
git checkout master && git pull
. Mistrz jest już aktualny.git checkout master && git pull
. Mistrz jest już aktualny.git merge topic-branch-A
git merge topic-branch-B
git push origin master
przed Alicegit push origin master
, co zostało odrzucone, ponieważ nie jest to szybkie przewijanie do przodu.git pull --rebase origin master
git push origin master
i wszyscy są szczęśliwi, że nie muszą czytać niepotrzebnego zatwierdzenia scalania, gdy patrzą na dzienniki w przyszłości.Zauważ, że konkretna gałąź, do której się włączasz, nie ma znaczenia w tym przykładzie. Mistrz w tym przykładzie może równie łatwo być gałęzią wydania lub gałęzią deweloperską. Kluczową kwestią jest to, że Alice i Bob jednocześnie łączą swoje lokalne oddziały ze współdzielonym zdalnym oddziałem.
źródło
git co master && git pull; git checkout topic-branch-A; git rebase master; git checkout master; git merge topic-branch-A; git push origin master
powtarzam, jeśli czyjaś próba opanowania nastąpiła przed moim. Chociaż widzę zwięzłe zalety twojego przepisu.Myślę, że powinieneś używać
git pull --rebase
, współpracując z innymi w tej samej branży. Jesteś w pracy → zatwierdzanie → praca → cykl zatwierdzania, a kiedy decydujesz się na wypchnięcie swojej pracy, twoje wypychanie jest odrzucane, ponieważ w tej samej gałęzi była równoległa praca. W tym momencie zawsze robiępull --rebase
. Nie używam squasha (do spłaszczania zatwierdzeń), ale bazuję, aby uniknąć dodatkowych zatwierdzeń scalania.Wraz ze wzrostem wiedzy na temat Git, patrzysz o wiele bardziej na historię niż na inne systemy kontroli wersji, z których korzystałem. Jeśli masz mnóstwo drobnych zatwierdzeń scalania, łatwo stracić ostrość większego obrazu, który dzieje się w twojej historii.
To właściwie jedyny raz, kiedy dokonuję zmiany wersji (*), a reszta mojego przepływu pracy oparta jest na scalaniu. Ale tak długo, jak robią to najczęściej polecający, historia wygląda o wiele lepiej.
(*) Podczas nauczania kursu Git kazałem uczniowi mnie za to aresztować, ponieważ w niektórych okolicznościach opowiadałem się również za zmianą gałęzi fabularnych. I przeczytał tę odpowiedź;) Takie bazowanie jest również możliwe, ale zawsze musi być zgodne z wcześniej ustalonym / uzgodnionym systemem i jako takie nie powinno być „zawsze” stosowane. I w tym czasie zwykle też nie robię
pull --rebase
, o to właśnie chodzi;)źródło
Nie sądzę, żeby istniał jakiś powód, aby nie używać
pull --rebase
- dodałem kod do Git specjalnie po to, aby mojegit pull
polecenie zawsze bazowało na wcześniejszych zatwierdzeniach.Przeglądając historię, nigdy nie jest interesujące wiedzieć, kiedy facet / gal pracujący nad funkcją przestał się synchronizować. Może to być przydatne dla faceta / dziewczyny, gdy on to robi, ale po to
reflog
jest. To tylko hałas dla wszystkich innych.źródło
pull --rebase
należy zawsze używać, dlaczego niepull
robi tego domyślnie?.gitconfig
aby niektóre opcje działały poprawnie. Myślę, że git rebase domyślnie robi coś złego, podobnie jak git tag itp. Jeśli się nie zgadzasz, nie musisz uzasadniać swojej opinii.master
, i jeśli gałąź, do której podchodzisz, nie została jeszcze upubliczniona. Jeśli wyciągniesz drugą rękę z gałęzi funkcji,master
będzie to bardziej odwrotne: nigdy nie ma powodu, aby używać--rebase
, prawda? To może być powód, dla którego nie jest domyślny. Odkryłem, że Rebases to sposób, w jaki zmiany powinny przechodzić od szczytu hierarchii w dół, a scalanie to sposób, w jaki przepływają z powrotem w górę. derekgourlay.com/blog/git-when-to-merge-vs-when-to-rebaseTylko pamiętaj:
Wybierz sposób obsługi swojego oddziału.
Lepiej poznaj różnicę między scalaniem a rebase :)
źródło
Myślę, że sprowadza się to do osobistych preferencji.
Czy chcesz ukryć swoje głupie błędy przed wprowadzeniem zmian? Jeśli tak,
git pull --rebase
jest idealny. Pozwala to później zmiażdżyć swoje zobowiązania do kilku (lub jednego). Jeśli masz fuzje w swojej (nienasyconej) historii, nie jest to takie łatwegit rebase
późniejszą.Osobiście nie mam nic przeciwko publikowaniu wszystkich moich głupich błędów, więc zwykle łączę się zamiast bazować.
źródło
git pull --rebase
może ukryć przepisywanie historii przed współpracownikiemgit push --force
. Polecam używaćgit pull --rebase
tylko, jeśli wiesz, że zapomniałeś forsować swoje zobowiązania, zanim zrobi to ktoś inny.Jeśli nic nie popełniłeś, ale twoje miejsce pracy nie jest czyste, tuż
git stash
przedtemgit pull
. W ten sposób nie będziesz w stanie po cichu przepisać swojej historii (co może po cichu usunąć część twojej pracy).źródło