W Git, jaka jest różnica między scalaniem - quassem a rebase?

363

Jestem nowy w Git i próbuję zrozumieć różnicę między squash a rebase. Jak rozumiem, wykonujesz squash podczas wykonywania bazy.

GiH
źródło

Odpowiedzi:

360

Oba git merge --squashi git rebase --interactivemogą powodować zatwierdzenie „zgniecione”.
Ale służą one innym celom.

spowoduje zgniecenie zatwierdzenia w gałęzi docelowej, bez zaznaczania relacji scalania.
(Uwaga: od razu nie powoduje zatwierdzenia: potrzebujesz dodatkowego git commit -m "squash branch")
Jest to przydatne, jeśli chcesz całkowicie wyrzucić gałąź źródłową, przechodząc od (schemat wzięty z pytania SO ):

 git checkout stable

      X                   stable
     /                   
a---b---c---d---e---f---g tmp

do:

git merge --squash tmp
git commit -m "squash tmp"

      X-------------------G stable
     /                   
a---b---c---d---e---f---g tmp

a następnie usunięcie tmpoddziału.


Uwaga: git mergema --commitopcję , ale nie można jej używać z --squash. To nigdy nie było możliwe do użycia --commiti --squashrazem.
Od wersji Git 2.22.1 (III kwartał 2019 r.) Wyraźnie zaznaczono tę niezgodność:

Zobacz zatwierdzenie 1d14d0c (24 maja 2019 r.) Autor: Vishal Verma ( reloadbrain) .
(Połączone przez Junio ​​C Hamano - gitster- w commit 33f2790 , 25 lipca 2019)

merge: odmówić --commitz--squash

Wcześniej, kiedy --squashzostał dostarczony, ' option_commit' został po cichu upuszczony. Mogło to być zaskakujące dla użytkownika, który próbował --commitjawnie zastąpić zachowanie squash bez zatwierdzania .

git/git builtin/merge.c#cmd_merge() teraz obejmuje:

if (option_commit > 0)
    die(_("You cannot combine --squash with --commit."));

odtwarza niektóre lub wszystkie twoje zmiany na nowej bazie, co pozwala ci zgnieść (lub ostatnio „naprawić”, zobacz to pytanie SO ), przechodząc bezpośrednio do:

git checkout tmp
git rebase -i stable

      stable
      X-------------------G tmp
     /                     
a---b

Jeśli zdecydujesz się zmiażdżyć wszystkie zatwierdzenia tmp(ale w przeciwieństwie do merge --squashniektórych możesz je odtworzyć, a innych zmiażdżyć).

Różnice są następujące:

  • squashnie dotyka gałęzi źródłowej ( tmptutaj) i tworzy pojedyncze zatwierdzenie tam, gdzie chcesz.
  • rebasepozwala przejść do tej samej gałęzi źródłowej (nadal tmp) z:
    • nowa baza
    • czystsza historia
VonC
źródło
11
Gjest c--d--e--f--gzgnieciony razem?
Wayne Conrad,
8
@Wayne: tak, G w tych przykładach reprezentuje tmpzgniecione razem.
VonC
3
@ Th4wn: Ponieważ Git uzasadnia migawkami całego projektu, Gnie będzie reprezentował tej samej zawartości niż z gpowodu zmian wprowadzonych przez X.
VCC
1
@VonC: nie jestem pewien tego ostatniego komentarza. Jeśli masz git merge --no-ff tempzamiast git merge --squash temp, to masz bardziej chaotyczną historię, ale możesz też robić rzeczy o git revert ewiele łatwiej. To brudna, ale szczera i pragmatyczna historia, a główna gałąź wciąż pozostaje dość czysta.
naught101
2
@ naught101 Zgadzam się. Jak wyjaśniono w stackoverflow.com/a/7425751/6309 , chodzi również o to, aby nie łamać się git bisectlub git blamegdy jest używane zbyt często (jak w git pull --no-ff: stackoverflow.com/questions/12798767/... ). W każdym razie nie ma jednego podejścia, dlatego w tym artykule opisano trzy ( stackoverflow.com/questions/9107861/... )
VonC
183

Scal zatwierdzenia: zachowuje wszystkie zatwierdzenia w gałęzi i przeplata je z zatwierdzeniami w gałęzi bazowejwprowadź opis zdjęcia tutaj

Scal squash: zachowuje zmiany, ale pomija poszczególne zatwierdzenia z historii wprowadź opis zdjęcia tutaj

Rebase: Przenosi całą gałąź funkcji na początek gałęzi master, skutecznie włączając wszystkie nowe commity w master

wprowadź opis zdjęcia tutaj

Więcej tutaj

Pani Ayub Ali Sarker
źródło
81

Scal squash scala drzewo (sekwencję zatwierdzeń) w jeden zatwierdzenie. Oznacza to, że zgniata wszystkie zmiany dokonane w n zatwierdzeniach w jednym zatwierdzeniu.

Rebasing polega na ponownym bazowaniu, to znaczy na wybraniu nowej bazy (zatwierdzenie nadrzędne) dla drzewa. Może termin rtęciowy na to jest bardziej wyraźny: nazywają to przeszczepem, ponieważ jest to po prostu: wybranie nowego gruntu (zatwierdzenie przez rodziców, root) dla drzewa.

Podczas wykonywania interaktywnego bazowania masz opcję zgniatania, wybierania, edytowania lub pomijania zatwierdzeń, które zamierzasz bazować.

Mam nadzieję, że to było jasne!

Mauricio Scheffer
źródło
7
Kiedy powinienem dokonać bazowania i kiedy powinienem zgnieść?
Martin Thoma,
31

Zacznijmy od następującego przykładu:

wprowadź opis zdjęcia tutaj

Teraz mamy 3 opcje scalić zmiany funkcji oddziału język gałęzi master :

  1. Scal zatwierdzenia
    Zachowa całą historię zatwierdzeń gałęzi funkcji i przeniesie je do gałęzi głównej
    .

  2. Rebase i scalanie Dołączą
    całą historię zatwierdzeń gałęzi funkcji z przodu gałęzi głównej
    NIE dodadzą dodatkowego zatwierdzenia.

  3. Squash and merge
    Zgrupuje wszystkie zatwierdzenia gałęzi funkcji w jednym zatwierdzeniu, a następnie doda je przed gałęzią główną.
    Dodanie dodatkowego fałszywego zatwierdzenia.

Poniżej możesz zobaczyć, jak gałąź główna będzie się opiekować każdym z nich.

wprowadź opis zdjęcia tutaj

We wszystkich przypadkach:
Możemy bezpiecznie USUNĄĆ gałąź funkcji .

ahmednabil88
źródło
1
czy możesz wyjaśnić, co to jest atrapa zatwierdzenia na 2. zdjęciu? Jestem początkującym w git.
Yusuf
1
@Yusuf, to tylko dodatkowe zatwierdzenie, które zawiera aktualizacje obu gałęzi, to domyślny komunikat zatwierdzenia = "Megre oddział XYZ w master"
ahmednabil88