Różnica między git pull a git pull --rebase


311

Kiedyś zacząłem używać git i nie do końca rozumiem zawiłości. Moje podstawowe pytanie tutaj polega na ustaleniu różnicy między git pulla git pull --rebase, ponieważ dodanie --rebaseopcji nie wydaje się robić czegoś zupełnie innego: wystarczy pociągnąć.

Pomóż mi zrozumieć różnicę.



3
TJ

Odpowiedzi:


326

git pull= git fetch+ git mergeprzed śledzeniem gałęzi upstream

git pull --rebase= git fetch+ git rebaseprzed śledzeniem gałęzi upstream

Jeśli chcesz wiedzieć jak git mergei czym się git rebaseróżnią, przeczytaj to .


12
Warto zauważyć, że powiedzenie git pull --rebasejest takie samo git fetchi git rebasezasadniczo jest, ale nie jest dokładnie semantycznie równoważne. Istnieją pewne różnice, z których niektóre wyjaśniono tutaj. gitolite.com/git-pull--rebase
w0rp

8
To, co nazwałbym „wygodnym kłamstwem”, pożyczył zdanie od Scotta Meyersa. To dobry sposób na wyjaśnienie tego niezależnie.
w0rp,

Bardzo krótko. Nie rozumiem różnicy. Co jest takiego ważnego fetch?
Zielony,

240

Czasami mamy upstream, który zmienił / przewinął gałąź, od której jesteśmy zależni. To może być duży problem - powodując dla nas bałaganiarskie konflikty, jeśli jesteśmy na niższych szczeblach.

Magia jest git pull --rebase

Normalne ściąganie git jest, mówiąc luźniej, czymś takim: (we wszystkich tych przykładach użyjemy zdalnego o nazwie origin i gałęzi o nazwie foo):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

Na pierwszy rzut oka możesz pomyśleć, że git pull --rebase robi to:

git fetch origin
git rebase origin/foo

Ale to nie pomoże, jeśli rebase poprzedzający wiązałby się z jakimś „squashingiem” (co oznacza, że ​​zmieniono łatki commits, nie tylko ich kolejność).

Co oznacza, że ​​git pull --rebase musi zrobić coś więcej. Oto wyjaśnienie tego, co robi i jak.

Powiedzmy, że Twoim punktem wyjścia jest:

a---b---c---d---e  (origin/foo) (also your local "foo")

Czas płynie, a na twoim własnym „foo” dokonałeś pewnych zmian:

a---b---c---d---e---p---q---r (foo)

Tymczasem, w przypływie antyspołecznej wściekłości, opiekun wyższego szczebla nie tylko zmienił swoje „foo”, ale nawet użył squasha lub dwóch. Jego łańcuch zatwierdzeń wygląda teraz następująco:

a---b+c---d+e---f  (origin/foo)

Git pull w tym momencie spowodowałby chaos. Nawet git fetch; git rebase origin / foo nie wyciąłby go, ponieważ zatwierdza „b” i „c” z jednej strony, a zatwierdza „b + c” z drugiej, powodowałoby konflikt. (I podobnie z d, e i d + e).

Co git pull --rebaserobi, w tym przypadku, to:

git fetch origin
git rebase --onto origin/foo e foo

To daje ci:

 a---b+c---d+e---f---p'---q'---r' (foo)

Nadal możesz mieć konflikty, ale będą to prawdziwe konflikty (między p / q / r a a / b + c / d + e / f), a nie konflikty spowodowane przez b / c sprzeczne z b + c itp.

Odpowiedź pochodzi z (i nieznacznie zmodyfikowano):
http://gitolite.com/git-pull--rebase


9
To najlepsza odpowiedź. Możesz zmienić końcowy wynik na, a---b+c---d+e---f---p'---q'---r' (foo)ponieważ zmiana bazy zmienia hasze.
Bastien

22
Ta odpowiedź została skopiowana i wklejona dosłownie z gitolite.com/git-pull--rebase i powinna zawierać informacje o licencji na licencję na tej stronie.
Wildcard

To świetne wytłumaczenie. Ale miałem sytuację, w której się zobowiązałem Ai wysłałem PR do repozytorium poprzedzającego, które zostało zaakceptowane. Potem, kiedy zrobiłem to git pull --rebaseprzeciwko repozytorium upstream, nie dostałem nowego A'zatwierdzenia na szczycie repozytorium upstream. W rzeczywistości nic nie A'istniało. Czy to dlatego, że Azostał włączony do systemu? A może dlatego, że nie było różnicy między wersją wstępną a moją zmienioną na wersję?
CMCDragonkai

Obecnie przechodzę samouczek Git i wykorzystałem tę odpowiedź, aby lepiej zrozumieć git pull --rebase. Ale jedną z rzeczy, która myli mnie w tej hipotetycznej sytuacji, jest to, że opiekun wyższego szczebla zmienił historię projektu, która została już wciągnięta do repozytoriów lokalnych programistów. Czy ogólnie nie jest to po prostu zła praktyka? Jeśli chciał zmiażdżyć historię zmian / przepisań, powinien to zrobić przed integracją z centralnym repozytorium, aby uniknąć tego rodzaju konfliktów.
bmcentee148

44

Załóżmy, że masz dwa zatwierdzenia w oddziale lokalnym:

      D---E master
     /
A---B---C---F origin/master

Po „git pull” pojawi się:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

Po „git pull --rebase” nie będzie punktu scalania G. Zauważ, że D i E stają się różnymi zatwierdzeniami:

A---B---C---F---D'---E'   master, origin/master

1
czy to nie A --- B --- C --- D '--- E' - F?
prgmrDev

5
@prgmrDev Dlaczego D i E byłyby wstawiane przed F?
Jon

1
Czy to nie jest dokładnie to, co git rebaserobi? Ale mówimy o tym git pull --rebase. I to są różne rzeczy.
Zielony,

10

W najprostszym przypadku braku kolizji

  • z rebase: bazuje na lokalnych zatwierdzeniach na zdalnym HEAD i nie tworzy scalenia / zatwierdzenia scalania
  • none / normal: scala i tworzy zatwierdzenie scalania

Zobacz też:

man git-pull

Dokładniej, git pull uruchamia git fetch z podanymi parametrami i wywołuje git merge, aby scalić odzyskane głowy gałęzi z bieżącą gałęzią. W przypadku --rebase uruchamia git rebase zamiast git merge.

Zobacz także:
Kiedy powinienem używać git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing


3
A w przypadku kolizji?
Rndm

1
Zostaniesz poproszony o ich ręczne rozwiązanie, a następnie - kontynuuj z rebase: git sdd modified-file; git rebase --continuelub scal: git add modified-file; git commit;gdzie modified-filetwój plik lokalny został zmodyfikowany ręcznie /
scaletool

Co jest takiego specjalnego fetch? Dlaczego stworzyli dwa rebaseprzepływy? 1) git rebasei 2) git pull --rebase?
Zielony,

7

Jest to ważne, aby zrozumieć różnicę między Scalaniem a Rebase.

Rebase to sposób, w jaki zmiany powinny przechodzić od szczytu hierarchii w dół, a scalanie to, jak przepływają z powrotem w górę.

Aby uzyskać szczegółowe informacje, patrz - http://www.derekgourlay.com/archives/428


Myślę, że twoja odpowiedź zawiera znacznie prostsze wyjaśnienie, które nie jest oczywiste w pozostałych odpowiedziach powyżej. Dzięki.
Aaron C
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.