Mam kolegę, który tak twierdzi git pull
jest szkodliwy i denerwuje się, gdy ktoś go używa.
git pull
Polecenia wydaje się być kanoniczny sposób zaktualizować lokalne repozytorium. Czy używanie git pull
stwarza problemy? Jakie to stwarza problemy? Czy istnieje lepszy sposób aktualizacji repozytorium git?
git pull --rebase
ustawić tę strategię jako domyślną dla nowych oddziałówgit config branch.autosetuprebase
--rebase
flagę dogit pull
synchronizacji lokalnej ze zdalną, a następnie odtwarza zmiany lokalne na podstawie zaktualizowanego lokalnego. Następnie, kiedy naciskasz, jedyne, co robisz, to dołączanie nowych zatwierdzeń na końcu pilota. Dość proste.Odpowiedzi:
Podsumowanie
Domyślnie
git pull
tworzy zatwierdzenia scalania, które zwiększają szum i złożoność historii kodu. Ponadtopull
ułatwia nie myśleć o tym, w jaki sposób zmiany mogą wpływać na nadchodzące zmiany.git pull
Komenda jest bezpieczny tak długo, jak to tylko wykonuje scala fast-forward. Jeśligit pull
jest skonfigurowany tylko do wykonywania połączeń szybkiego przewijania do przodu, a gdy scalanie szybkiego przewijania nie jest możliwe, Git zakończy działanie z błędem. To da ci możliwość przestudiowania nadchodzących zatwierdzeń, zastanowienia się, w jaki sposób mogą one wpłynąć na twoje lokalne zatwierdzenia, i wybrania najlepszego sposobu działania (scalenie, zmiana bazy, resetowanie itp.).Dzięki Git 2.0 i nowszym możesz uruchomić:
aby zmienić domyślne zachowanie na szybkie przewijanie do przodu. W wersjach Git od 1.6.6 do 1.9.x musisz przyzwyczaić się do pisania:
Jednak w przypadku wszystkich wersji Git zalecam skonfigurowanie
git up
aliasu:i używanie
git up
zamiastgit pull
. Wolę ten alias niżgit pull --ff-only
ponieważ:origin/*
gałęzie, które już nie istnieją pod prąd.Problemy z
git pull
git pull
nie jest złe, jeśli jest właściwie używane. Kilka ostatnich zmian w Git ułatwiłogit pull
prawidłowe korzystanie , ale niestety domyślne zachowanie zwykłegogit pull
ma kilka problemów:git pull
Problemy te opisano bardziej szczegółowo poniżej.
Historia nieliniowa
Domyślnie
git pull
polecenie jest równoważne z uruchomieniem,git fetch
po którym następujegit merge @{u}
. Jeśli w lokalnym repozytorium znajdują się nieprzypisane zatwierdzenia, część scalaniagit pull
tworzy zatwierdzenie scalania.Nie ma nic złego w zatwierdzeniach scalania, ale mogą być niebezpieczne i powinny być traktowane z szacunkiem:
Oczywiście jest czas i miejsce na fuzje, ale zrozumienie, kiedy fuzje powinny i nie powinny być używane, może poprawić użyteczność repozytorium.
Zauważ, że celem Git jest ułatwienie dzielenia się i korzystania z ewolucji bazy kodu, a nie dokładne zapisywanie historii dokładnie w miarę jej rozwoju. (Jeśli się nie zgadzasz, rozważ
rebase
polecenie i powód, dla którego zostało utworzone). Zatwierdzenia scalania utworzone przezgit pull
nie przekazują użytecznej semantyki innym użytkownikom - po prostu mówią, że ktoś inny przepchnął się do repozytorium, zanim skończysz wprowadzać zmiany. Dlaczego owe zatwierdzenia scalania są, jeśli nie mają znaczenia dla innych i mogą być niebezpieczne?Możliwe jest skonfigurowanie
git pull
bazowania zamiast scalania, ale ma to również problemy (omówione później). Zamiast tegogit pull
powinien być skonfigurowany tak, aby wykonywał tylko szybkie przewijanie do przodu.Ponowne wprowadzenie przywróconych zobowiązań
Załóżmy, że ktoś zmienia gałąź i popycha ją siła. Zasadniczo nie powinno tak się zdarzyć, ale czasami jest konieczne (np. Aby usunąć plik dziennika 50GiB, który został przypadkowo zatwierdzony i wypchnięty). Scalenie wykonane przez
git pull
spowoduje scalenie nowej wersji gałęzi upstream ze starą wersją, która nadal istnieje w lokalnym repozytorium. Jeśli popchniesz wynik, widelce i pochodnie zaczną nadciągać.Niektórzy mogą twierdzić, że prawdziwym problemem jest wymuszanie aktualizacji. Tak, generalnie wskazane jest unikanie wypychania siły, gdy tylko jest to możliwe, ale czasami są one nieuniknione. Programiści muszą być przygotowani na radzenie sobie z aktualizacjami wymuszonymi, ponieważ czasem będą się one zdarzały. Oznacza to, że nie ślepo łączy się stare zobowiązania za pomocą zwykłego
git pull
.Zaskocz modyfikacje katalogu roboczego
Nie ma możliwości przewidzenia, jak będzie wyglądał katalog roboczy lub indeks, dopóki nie
git pull
zostanie wykonane. Mogą istnieć konflikty scalania, które musisz rozwiązać, zanim będziesz mógł zrobić cokolwiek innego, może wprowadzić plik dziennika 50GiB do katalogu roboczego, ponieważ ktoś przypadkowo go wypchnął, może zmienić nazwę katalogu, w którym pracujesz itp.git remote update -p
(lubgit fetch --all -p
) pozwala spojrzeć na zobowiązania innych osób, zanim zdecydujesz się na scalenie lub zmianę bazy, co pozwoli ci stworzyć plan przed podjęciem działań.Trudność w sprawdzaniu zobowiązań innych osób
Załóżmy, że jesteś w trakcie wprowadzania zmian i ktoś inny chce, abyś sprawdził niektóre zatwierdzone przez siebie zmiany.
git pull
Operacja scalania (lub rebase) modyfikuje katalog roboczy i indeks, co oznacza, że katalog roboczy i indeks muszą być czyste.Możesz użyć,
git stash
a następniegit pull
, ale co robisz, gdy skończysz sprawdzanie? Aby wrócić do miejsca, w którym byłeś, musisz cofnąć scalenie utworzone przezgit pull
i zastosować skrytkę.git remote update -p
(lubgit fetch --all -p
) nie modyfikuje katalogu roboczego lub indeksu, więc można go bezpiecznie uruchomić w dowolnym momencie - nawet jeśli wprowadziłeś zmiany etapowe i / lub niestabilne. Możesz wstrzymać to, co robisz i sprawdzić czyjeś zatwierdzenie, nie martwiąc się o ukrywanie lub dokończenie zatwierdzenia, nad którym pracujesz.git pull
nie daje ci takiej elastyczności.Powrót do zdalnego oddziału
Typowym wzorcem użycia Gita jest
git pull
wprowadzenie najnowszych zmian, a następniegit rebase @{u}
wyeliminowanie wprowadzonego zatwierdzenia scalaniagit pull
. To wspólne wystarczy, że Git ma kilka opcji konfiguracyjnych, aby zmniejszyć te dwa kroki do jednego kroku mówiącgit pull
wykonać rebase zamiast seryjnej (patrzbranch.<branch>.rebase
,branch.autosetuprebase
ipull.rebase
opcje).Niestety, jeśli masz nieprzypisane zatwierdzenie scalania, które chcesz zachować (np. Zatwierdzenie scalające wypchniętą gałąź funkcji do
master
), ani rebase-pull (git pull
zbranch.<branch>.rebase
ustawionym natrue
), ani merge-pull (git pull
zachowanie domyślne ), po którym następuje rebase będzie działać. Jest tak, ponieważgit rebase
eliminuje scalenia (linearyzuje DAG) bez--preserve-merges
opcji. Operacji rebase-pull nie można skonfigurować w celu zachowania scalania, a połączenie-pull, po którym następujegit rebase -p @{u}
, nie eliminuje scalenia spowodowanego przez pull-pull. Aktualizacja: Dodano Git v1.8.5git pull --rebase=preserve
igit config pull.rebase preserve
. Powodujągit pull
togit rebase --preserve-merges
po pobraniu zatwierdzeń poprzedzających. (Dzięki funkaster za heads-up!)Czyszczenie usuniętych gałęzi
git pull
nie przycina gałęzi zdalnego śledzenia odpowiadających gałęziom, które zostały usunięte ze zdalnego repozytorium. Na przykład, jeśli ktoś usunie gałąźfoo
ze zdalnego repozytorium, nadal zobaczyszorigin/foo
.Prowadzi to do przypadkowego wskrzeszenia zabitych gałęzi przez użytkowników, którzy uważają, że nadal są aktywni.
Lepsza alternatywa: użyj
git up
zamiastgit pull
Zamiast tego
git pull
zalecam utworzenie i używanie następującegogit up
aliasu:Ten alias pobiera wszystkie najnowsze zatwierdzenia ze wszystkich gałęzi upstream (przycinanie martwych gałęzi) i próbuje przewinąć gałąź lokalną do najnowszego zatwierdzenia w gałęzi upstream. Jeśli się powiedzie, nie będzie żadnych lokalnych zatwierdzeń, więc nie będzie ryzyka konfliktu scalania. Przewijanie do przodu nie powiedzie się, jeśli istnieją lokalne (niepodawane) zatwierdzenia, co daje możliwość przejrzenia zatwierdzeń przed podjęciem działania.
To wciąż modyfikuje katalog roboczy w nieprzewidywalny sposób, ale tylko wtedy, gdy nie masz żadnych lokalnych zmian. W przeciwieństwie do
git pull
,git up
nigdy nie spowoduje wyświetlenia monitu oczekującego rozwiązania konfliktu scalania.Inna opcja:
git pull --ff-only --all -p
Poniższa wersja stanowi alternatywę dla powyższego
git up
aliasu:Ta wersja
git up
ma takie samo zachowanie jak poprzednigit up
alias, z wyjątkiem:-p
argument przekazywanyfetch
), która może ulec zmianie w przyszłych wersjach GitaJeśli korzystasz z Git 2.0 lub nowszej wersji
W wersji Git 2.0 i nowszych możesz skonfigurować
git pull
domyślną funkcję tylko szybkiego przewijania do przodu:To powoduje,
git pull
że tak się zachowujegit pull --ff-only
, ale nadal nie pobiera wszystkich zatwierdzeń wcześniejszych ani nie usuwa starychorigin/*
gałęzi, więc nadal wolęgit up
.źródło
git remote update -p
jest równoważne zgit fetch --all -p
. Mam w zwyczaju pisać,git remote update -p
bo kiedyśfetch
nie miałem takiej-p
możliwości. Jeśli chodzi o prowadzenie!
, zobacz opisalias.*
wgit help config
. Mówi: „Jeśli rozszerzenie aliasu jest poprzedzone wykrzyknikiem, będzie traktowane jak polecenie powłoki”.pull.ff
konfigurację, która wydaje się osiągać to samo, bez aliasów.git up
brzmi jak interesująca alternatywa.git pull
.Moja odpowiedź pochodzi z dyskusji, która się pojawiła na HackerNews:
Kusi mnie, aby po prostu odpowiedzieć na pytanie, stosując Prawo Betteridge z Nagłówków: Dlaczego jest
git pull
uważane za szkodliwe? To nie jestźródło
git pull
. Może to jednak kolidować z niektórymi szkodliwymi praktykami, takimi jak chęć przepisania historii bardziej niż jest to absolutnie konieczne. Ale git jest elastyczny, więc jeśli chcesz go używać w inny sposób, zrób to. Ale to dlatego, że (cóż, @Richard Hansen) chcesz zrobić coś niezwykłego w git, a nie dlatego, żegit pull
jest szkodliwy.git rebase
i uważają zagit pull
szkodliwe? Naprawdę?git pull
bez--rebase
opcji jest kierunek scalania, który tworzy. Kiedy spojrzysz na różnicę, wszystkie zmiany w tym scaleniu należą teraz do osoby, która pociągnęła, a nie do osoby, która dokonała zmian. Podoba mi się przepływ pracy, w którym scalanie jest zarezerwowane dla dwóch oddzielnych gałęzi (A -> B), więc zatwierdzenie scalania jest jasne, co zostało wprowadzone, a zmiana bazy jest zarezerwowana na aktualizację w tym samym oddziale (zdalne A -> lokalne A )Nie jest uważane za szkodliwe, jeśli używasz Git poprawnie. Widzę, jak wpływa to na ciebie negatywnie, biorąc pod uwagę twój przypadek użycia, ale możesz uniknąć problemów po prostu nie modyfikując wspólnej historii.
źródło
git pull
kwestię : jeśli każdy pracuje we własnym oddziale (co moim zdaniem jest właściwym sposobem korzystania z git), nie stanowi to żadnego problemu. Rozgałęzienie w git jest tanie.Zaakceptowana odpowiedź twierdzi
ale od wersji 1.8.5 Git , która postdatuje tę odpowiedź, możesz to zrobić
lub
lub
W docs powiedzieć
Ta poprzednia dyskusja zawiera bardziej szczegółowe informacje i diagramy: git pull --rebase --preserve-scales . Wyjaśnia również, dlaczego
git pull --rebase=preserve
to nie to samogit pull --rebase --preserve-merges
, co nie robi właściwej rzeczy.Ta inna poprzednia dyskusja wyjaśnia, co faktycznie robi wariant rebase z zachowaniem-scalaniem i jak jest on o wiele bardziej złożony niż zwykły rebase: Co dokładnie robi „rebase - zachowaj-scala” gita (i dlaczego?)
źródło
Jeśli przejdziesz do starego repozytorium git, uruchom alias, który sugeruje, że jest inny. https://github.com/aanand/git-up
git config --global alias.up 'pull --rebase --autostash'
To działa idealnie dla mnie.
źródło