Dlaczego łączę „pochodzenie / rozwój” gałęzi zdalnego śledzenia w programowanie?

125

Tylko ja w mojej organizacji dokonuję zatwierdzeń z następującym komunikatem:

Połącz gałąź zdalnego śledzenia „pochodzenie / rozwój” w programować

Nie jestem pewien, co robię, żeby je wywołać, ale chciałbym przestać.

Jakie polecenie wydaję, aby utworzyć to zatwierdzenie i jakie jest właściwe polecenie, którego powinienem użyć, aby go nie wyprodukować?

Jordan Feldstein
źródło
1
Odpowiedź Richarda Hansena jest w porządku. Ale myślę, że może to być mylące dla początkujących. Moim rozwiązaniem jest ciągłe ciągnięcie - wstrzymanie, ale aby uniknąć niebezpieczeństwa, chowam zmiany przed pociągnięciem. Następnie po pociągnięciu nakładam. Rozwiązuję konflikty. Wreszcie mogę zatwierdzić i naciskać.
Johnjohn
Czy git pull --autostash --rebasedziała dla Ciebie @Johnjohn?
sourcedelica

Odpowiedzi:

206

git pullprawdopodobnie tworzy zatwierdzenie. Jeśli wykonasz lokalne zatwierdzenie, a następnie uruchomiszgit pull po tym, jak ktoś inny umieści zatwierdzenie w repozytorium, Git pobierze zatwierdzenie innego programisty, a następnie scali go z lokalną gałęzią.

Jak uniknąć tych zatwierdzeń scalających w przyszłości

Mógłbyś użyć, git pull --rebaseaby temu zapobiec w przyszłości, ale ponowne bazowanie ma swoje niebezpieczeństwa i zalecam pullcałkowite unikanie tego .

Zamiast tego zachęcam do przestrzegania tego schematu użytkowania:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

Wyjaśnienie

  • git remote update -ppobiera wszystkie zatwierdzenia ze zdalnych repozytoriów i aktualizuje zdalne gałęzie śledzenia (np origin/master.). NIE dotyka twojego katalogu roboczego, indeksu ani lokalnych gałęzi.

    Te -pśliwki argumentów usunięte oddziałów wydobywczych. Zatem jeśli foooddział zostanie usunięty z originrepozytorium, git remote update -pautomatycznie usunie Twój origin/fooref.

  • git merge --ff-only @{u}mówi Gitowi, aby scalił gałąź upstream ( @{u}argument) z gałęzią lokalną, ale tylko wtedy, gdy gałąź lokalna może zostać „szybko przekazana” do gałęzi upstream (innymi słowy, jeśli się nie rozdzieliła).

  • git rebase -p @{u}efektywnie przenosi zatwierdzenia, które stworzyłeś, ale nie zostały jeszcze umieszczone na górnej gałęzi, co eliminuje potrzebę tworzenia głupich zatwierdzeń scalających, których próbujesz uniknąć. Poprawia to liniowość historii rozwoju, ułatwiając przeglądanie.

    Ta -popcja mówi Gitowi, aby zachować scalenia. Zapobiega to linearyzacji zatwierdzeń przez Git. Jest to ważne, jeśli na przykład scaliłeś gałąź funkcji z master. Bez tego -pkażde zatwierdzenie w gałęzi feature byłoby zduplikowane masterjako część linearyzacji wykonywanej przez git rebase. Utrudniłoby to przeglądanie historii rozwoju, a nie łatwiejsze.

    Uwaga : git rebasemożesz nie robić tego, czego oczekujesz, więc przejrzyj wyniki przed naciśnięciem. Na przykład:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Preferuję to podejście git pull --rebasez następujących powodów:

  • Pozwala to zobaczyć nadchodzące zmiany typu upstream przed zmodyfikowaniem historii w celu ich uwzględnienia.
  • Umożliwia przekazanie opcji -p( --preserve-merges) dogit rebase w przypadku konieczności zmiany bazy zamierzonego scalenia (np. Scalenia już wypchniętej gałęzi funkcji do master).

Stenografia: git up zamiastgit pull

Aby ułatwić powyższe, polecam utworzenie aliasu o nazwie up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Teraz wszystko, co musisz zrobić, aby zaktualizować swój oddział, to uruchomić:

git up

zamiast git pull . Jeśli pojawi się błąd, ponieważ lokalna gałąź oddzieliła się od gałęzi upstream, jest to wskazówka do ponownej bazy danych.

Dlaczego nie git pull --rebase ?

Bieganie git pull --rebasejest równoznaczne z bieganiem, git fetchpo którym następujegit rebase . To próbuje szybko przewinąć do nowych zatwierdzeń upstream, ale jeśli to nie jest możliwe, to przełoży twoje lokalne zatwierdzenia do nowych zatwierdzeń upstream. Zwykle jest to w porządku, ale bądź ostrożny:

  • Rebase to zaawansowany temat i przed zmianą bazy należy zrozumieć konsekwencje.
  • git pull --rebasenie daje możliwości zbadania zatwierdzeń przed ich wprowadzeniem. W zależności od tego, co upstream zmieniło, to całkiem możliwe, że rebase jest zła praca-a rebase --onto, merge, reset, lub push -fmoże być bardziej odpowiednie niż zwykłyrebase .
  • Nie jest (obecnie) możliwe przejście --preserve-mergesdo operacji rebase, więc każde celowe scalenie gałęzi funkcji zostanie zlinearyzowane, odtwarzając (a tym samym powielając) wszystkie zatwierdzenia gałęzi funkcji.

„Naprawianie” istniejącego zatwierdzenia scalającego utworzonego przez git pull

Jeśli jeszcze nie wypchnąłeś zatwierdzenia scalającego utworzonego przez git pull, możesz zmienić bazę zatwierdzenia scalającego. Zakładając, że nie dokonałeś żadnych celowych scaleń (np. Scalenie już wypchniętej gałęzi funkcji do bieżącej gałęzi), wykonaj następujące czynności:

git rebase @{u}

Powyższe polecenie nakazuje Gitowi wybranie wszystkich zatwierdzeń nie-scalających dostępnych z HEAD(bieżącego zatwierdzenia), pomniejszonych o wszystkie zatwierdzenia osiągalne z @{u}(co jest skrótem dla "gałęzi upstream", tj. origin/masterJeśli HEADjest master), powtórka (wybór wiśniowy ) je na górnej gałęzi, a następnie przenieś odwołanie do bieżącej gałęzi, aby wskazywało wynik ponownego odtworzenia zatwierdzeń. To skutecznie przenosi zatwierdzenie nie-scalające do ostatniego zatwierdzenia nadrzędnego, co eliminuje scalanie utworzone przezgit pull .

Jeśli masz celowe zatwierdzenie przez scalanie, nie chcesz uruchamiać, git rebase @{u}ponieważ odtworzy wszystko z innej gałęzi. Radzenie sobie z tym przypadkiem jest znacznie bardziej skomplikowane, dlatego dobrze jest go używać git upi git pullcałkowicie unikać . Prawdopodobnie będziesz musiał użyć, resetaby cofnąć scalenie utworzone przez, pulla następnie to zrobić git rebase -p @{u}. -pArgument git rebasenie działa niezawodnie dla mnie, więc może skończyć się konieczności korzystania resetcofnąć celowe seryjnej, aktualizować swój lokalny oddział do @{u}, a następnie przerobić celowe seryjnej (co jest uciążliwe, gdyby nie było dużo owłosionej seryjnej konflikty).

Richard Hansen
źródło
+1 za omawianie --preserve-scala, z wyjątkiem tego, że w rzeczywistości nie udokumentowałeś tego w poleceniach, które kazałeś mu uruchomić, więc -1 za to.
Seth Robertson
@Seth: Dzięki za komentarz; Zaktualizowałem odpowiedź, aby polecić -p. Unikałem wcześniejszego polecania go, ponieważ nie jest potrzebny zbyt często, a jego zachowanie nie jest dobrze udokumentowane.
Richard Hansen
3
Jaka jest różnica między git remote update -pi git fetch?
eckes
3
@eckes: git remote update -pto to samo co git fetch --all -p. Przyzwyczaiłem się do używania z git remote update -ppowrotem, kiedy fetchnie miałem takiej -pmożliwości.
Richard Hansen,
1
@ user1914692: Po zakończeniu scalania Git zaktualizuje gałąź lokalną tak, aby wskazywała na nowo utworzone zatwierdzenie scalania, a nie na to samo zatwierdzenie co w gałęzi zdalnej. Problemem jest to nowe zatwierdzenie scalające, zwłaszcza gdy jest wypychane.
Richard Hansen
18
git fetch
git rebase origin/master

Że należy to zrobić. Lub jeśli chcesz nadal używać pull

git pull --rebase

Możesz również ustawić tę gałąź w swoim configu, aby automatycznie przestawiać bazę, lub ustawić ją w ten sposób automatycznie dla wszelkich innych tworzonych w przyszłości gałęzi śledzenia. Następnie możesz wrócić do zwykłego używania

git pull

Więcej na ten temat w sekcji „Wyciągnij z rebase zamiast scalać” na tej stronie:

http://mislav.uniqpath.com/2010/07/git-tips/

Adam Dymitruk
źródło