Git'te merge --squash ve rebase arasındaki fark nedir?


363

Gitmek için yeniyim ve bir squash ve bir rebase arasındaki farkı anlamaya çalışıyorum. Anladığım kadarıyla, bir rebase yaparken bir squash yapıyorsunuz.

Yanıtlar:


360

Her ikisi de git merge --squashve git rebase --interactivebir "ezilmiş" taahhüt üretebilir.
Ancak farklı amaçlara hizmet ederler.

herhangi bir birleştirme ilişkisi işaretlemeden hedef dalda ezilmiş bir taahhüt üretecektir.
(Not: hemen bir taahhüt vermez: ek bir ihtiyacınız var git commit -m "squash branch")
Bu, kaynak dalı tamamen atmak istiyorsanız ( SO sorusundan alınan şema ) yararlıdır :

 git checkout stable

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

için:

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

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

ve sonra tmpşubeyi silme .


Not: git mergebir --commitseçeneği vardır , ancak ile kullanılamaz --squash. O was asla kullanmak mümkün --commitve --squashbirlikte.
Git 2.22.1 (3Ç 2019) tarihinden bu yana, bu uyumsuzluk açıkça belirtilmiştir:

Bkz . Vishal Verma ( ) tarafından taahhüt edilen 1d14d0c (24 Mayıs 2019 ) . (Göre Birleştirilmiş - Junio Cı Hamano - içinde 33f2790 tamamlama 2019 25 Tem)reloadbrain
gitster

merge: Çöp --commitile--squash

Daha önce, --squashtedarik edildiğinde , ' option_commit' sessizce düştü. Bu, squash'ın kesin olmayan davranışını --commitaçıkça kullanarak geçersiz kılmaya çalışan bir kullanıcı için şaşırtıcı olabilirdi .

git/git builtin/merge.c#cmd_merge() şimdi içerir:

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

taahhütlerinizin bir kısmını veya tamamını yeni bir temelde tekrar oynatır ve doğrudan aşağıdakilere giderek ezmenize (veya daha yakın zamanda "düzeltmeye", bu SO sorusuna bakın ) izin verir:

git checkout tmp
git rebase -i stable

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

Tüm taahhütlerini ezmeyi seçerseniz tmp(ancak aksine merge --squash, bazılarını tekrar oynatmayı ve diğerlerini ezmeyi seçebilirsiniz).

Yani farklılıklar:

  • squashkaynak dalınıza ( tmpburada) dokunmaz ve istediğiniz yerde tek bir taahhüt oluşturur.
  • rebaseaşağıdakilerle aynı kaynak dalda (hareketsiz tmp) devam etmenizi sağlar :
    • yeni bir üs
    • daha temiz bir tarih

11
Gedilir c--d--e--f--gbirlikte ezilmiş?
Wayne Conrad

8
@Wayne: evet, bu örneklerde G, tmpbirlikte ezilen taahhütleri temsil eder.
VonC

3
@ Th4wn: Git, tüm projelerin anlık görüntülerine neden Golduğundan g, getirdiği değişiklikler nedeniyle aynı içeriği temsil etmez X.
VonC

1
@VonC: bu son yorumdan emin değilim. Eğer bir varsa git merge --no-ff tempyerine git merge --squash temp, o zaman bir Messier geçmişini olsun, ama aynı zamanda gibi şeyler yapabilirsiniz git revert eçok daha kolay. Dağınık, ama dürüst ve pragmatik bir tarih ve ana şube hala oldukça temiz.
naught101

2
@ naught101 Kabul ediyorum. Bununla birlikte, stackoverflow.com/a/7425751/6309'da açıklandığı gibi, kırılmama git bisectveya git blameçok sık kullanıldığında da (şu şekilde olduğu gibi git pull --no-ff: stackoverflow.com/questions/12798767/… ). Zaten tek bir yaklaşım yok, bu yüzden bu makalede üç açıklanmıştır ( stackoverflow.com/questions/9107861/… )
VonC

183

Birleştirme taahhütleri: şubenizdeki tüm taahhütleri tutar ve temel şubedeki taahhütlerle serpiştirirresim açıklamasını buraya girin

Squash Birleştir: değişiklikleri korur, ancak bireyin tarihte taahhüt ettiği şeyi ihmal eder resim açıklamasını buraya girin

Rebase: Bu, tüm özellik dalını ana dalın ucunda başlamak için taşır ve tüm yeni taahhütleri etkili bir şekilde ana programa dahil eder

resim açıklamasını buraya girin

Burada daha fazlası


81

Birleştirme kabağı, bir ağacı (bir dizi işlem) tek bir işlemde birleştirir. Yani, bir squashes yapılan tüm değişiklikleri n tek içine kaydedilmesini işlemek.

Yeniden inşası yeniden temel alır, yani bir ağaç için yeni bir taban (üst düzey taahhüt) seçer. Belki bunun mercurial terimi daha açıktır: buna transplant diyorlar çünkü bu sadece: bir ağaç için yeni bir zemin (ebeveyn taahhüdü, kök) seçmek.

Etkileşimli bir rebase yaparken, rebase yapacağınız taahhütleri ezme, seçme, düzenleme veya atlama seçeneği sunulur.

Umarım bu açıktı!


7
Ne zaman yeniden temellendirmeliyim ve ne zaman ezmeliyim?
Martin Thoma

31

Aşağıdaki örnekle başlayalım:

resim açıklamasını buraya girin

Şimdi değişikliklerini birleştirmek 3 seçenek var özellik dalı haline ana şube :

  1. Birleştirme taahhütleri
    Tüm özellik dalının geçmiş taahhütlerini saklayacak ve bunları ana şubeye taşıyacak
    Ekstra kukla taahhütler ekleyecektir.

  2. Yeniden oluşturma ve birleştirme Ana dalın önündeki özellik dalının
    tüm taahhüt tarihini ekler Ekstra kukla taahhüt eklemez.

  3. Squash ve birleştirme
    Will grubu, tüm özellik dalı haline kaydedilmesini birinin taahhüt önünde ekleme daha sonra ana dal
    ekstra kukla taahhüt ekler misin.

Ana dalın her birine nasıl bakacağını aşağıda bulabilirsiniz .

resim açıklamasını buraya girin

Her durumda: Özellik dalını
güvenle Silebiliriz .


1
2. resimde kukla taahhüt nedir açıklayabilir misiniz? Git'e yeni başlayan biriyim.
Yusuf

1
@Yusuf, her iki şube güncellemesini de içeren fazladan bir taahhüt, varsayılan taahhüt mesajı = "Megre dalı XYZ master'a"
ahmednabil88
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.