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.

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

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


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!


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 .


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
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.