Kiraz seçiminden sonra git nasıl birleşir?


190

Bir masterşubemiz olduğunu hayal edelim .

Sonra bir newbranch

git checkout -b newbranch

ve iki yeni taahhütte bulununnewbranch : commit1 ve commit2

Sonra ustaya geçiyoruz ve cherry-pick

git checkout master
git cherry-pick hash_of_commit1

İçine bakıyor gitkbiz görüyoruz commit1 yüzden teknik olarak iki farklı onaylatabilirsiniz vardır ve onun kiraz aldı versiyonu farklı karmaları var.

Sonunda birleştirme newbranchiçine master:

git merge newbranch

farklı karmaları olan bu iki taahhüdün, aynı değişikliklerin iki kez uygulanması gerektiğini ima etmelerine rağmen, sorunsuz bir şekilde birleştirildiğini görüyoruz, bu yüzden bunlardan biri başarısız olmalı.

Git gerçekten birleştirme sırasında taahhüt içeriğinin akıllıca analizini yapıyor mu ve değişikliklerin iki kez uygulanmaması gerektiğine mi karar veriyor veya bu taahhütler dahili olarak birbirine bağlı olarak mı işaretleniyor?

Yanıtlar:


131

Kısa cevap

Endişelenme, Git halledecek.

Uzun cevap

SVN 1'den farklı olarak Git, taahhütleri delta formatında depolamaz, ancak anlık görüntü tabanlı 2,3'tür . SVN, birleştirilen her bir taahhüdü bir yama olarak uygulamaya çalışırken (ve tam olarak açıkladığınız nedenden dolayı başarısız olursa) Git genellikle bu senaryoyu gerçekleştirebilir.

Birleştirirken Git, her iki HEAD taahhüdünün anlık görüntülerini yeni bir anlık görüntüde birleştirmeye çalışacaktır. Kodun veya dosyanın bir kısmı her iki anlık görüntüde de aynıysa (örneğin, bir taahhüt zaten kiraz olarak seçilmiş olduğu için) Git buna dokunmaz.

Kaynaklar

1 Subversion'da Skip-Deltas
2 Git Temelleri
3 Git nesne modeli


40
Aslında, birleştirme konusunda endişelenmeniz gerektiğini söyleyebilirim ve "git bunu halledecek" iyi bir kural değil.
cregox

4
Aslında birleştirme bazı durumlarda yinelenen içerikle sonuçlanabilir. Git bazen üstesinden gelir, ama bazen üstesinden gelmez.
donquixote

Bu çok yanlış. Got hemen hemen tüm bulabilen formlarda dosya dosyalarını saklar. Ve doğru hatırlıyorsam SVN anlık görüntüleri saklamak için kullanılır.
he_the_great

2
@he_the_great, hayır. SVN'nin atlama-delta depolama biçimi (! = Anlık görüntüler) kılavuzda iyi belgelenmiştir . Ve gerçekten kasten ne demek istediğini anlamıyorum . Ben anadili değilim, ama bunun gerçek bir kelime olmadığından eminim.
helmbert

2
@he_the_great Ama packfiles bile bir dosya için verilen herhangi bir karma tam dosya ile sonuçlanır. Evet, deltaları kullanarak sıkıştırır, ancak bir taahhütteki değişiklikler için bir delta değil, bir dosya için karmalar arasındaki bir deltadır. Tamamlama nesnesi söz konusu olduğunda, tam bir dosya için karmaya başvuran bir ağaca başvuruyor. Kaputun altında verilerin sıkıştırılması git'in çalışma şeklini etkilemez. Git, taahhüt ettikleri kadar eksiksiz dosyaları saklar, SVN anladığım kadarıyla taahhütler için deltaları saklar.
Peter Olson

44

Böyle bir birleşmeden sonra tarihte iki kez kiraz toplama taahhütleriniz olabilir.

Bunu önlemek için çözüm Ben yinelenen (kiraz aldı) dalları için birleştirme önce rebase kullanımı taahhüt taahhüt makaleden alıntı :

git cherry-pick'ten sonra git birleştirme: yinelenen işlemlerden kaçınma

Ana dal ve bir dal b olduğumuzu düşünün:

   o---X   <-- master
    \
     b1---b2---b3---b4   <-- b

Şimdi acilen b1 ve b3 komutlarına master olarak ihtiyacımız var, ancak b'de kalan komisyonlara değil. Yaptığımız şey ana dalı kontrol etmek ve kiraz toplama b1 ve b3'ü taahhüt ediyor:

$ git checkout master
$ git cherry-pick "b1's SHA"
$ git cherry-pick "b3's SHA"

Sonuç:

   o---X---b1'---b3'   <-- master
    \
     b1---b2---b3---b4   <-- b

Diyelim ki ustaya başka bir taahhütte bulunuyoruz ve şunları elde ediyoruz:

   o---X---b1'---b3'---Y   <-- master
    \
     b1---b2---b3---b4   <-- b

Şimdi b dalını ustayla birleştirirsek:

$ git merge b

Aşağıdakileri alırız:

   o---X---b1'---b3'---Y--- M  <-- master
     \                     /
      b1----b2----b3----b4   <-- b

Bu, b1 ve b3 tarafından yapılan değişikliklerin geçmişte iki kez görüneceği anlamına gelir. Bundan kaçınmak için birleştirme yerine yeniden pazarlayabiliriz:

$ git rebase master b

Hangi verimi:

   o---X---b1'---b3'---Y   <-- master
                        \
                         b2'---b4'   <-- b

En sonunda:

$ git checkout master
$ git merge b

bize verir:

   o---X---b1'---b3'---Y---b2'---b4'   <-- master, b

DÜZENLEME David Limon yorum tarafından sözde Düzeltmeler


1
Rebase hakkında büyük ipucu! kiraz toplanan tüm taahhütleri otomatik olarak 'atlayacak'.
iTake

2
Dürüst olmak gerekirse, gerçek olamayacak kadar iyi görünüyor, gözlerimle görmek zorundayım. Ayrıca rebase taahhütleri değiştirir, son zaman çizelgeniz olmalıdır---Y---b2'---b4'
David Lemon

Mükemmel çalışıyor. Tarihte iki kez kiraz aldı taahhüt istemiyorsanız çok yararlı.
user2350644

1
Rebase güzel olsa da, bunu kullanmanın tehlikesi, eski b'den oluşturulan çatalların veya dalların senkronize olmayacağı ve kullanıcıların git reset --hard ve git gibi şeylere başvurması gerekebileceği belirtilmelidir. push -f?
JHH

1
@JHH bu yüzden burada yerel şubeyi yeniden
temellendiriyoruz
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.