Neden bu kadar çok proje “git birleştirme” yerine “git rebase” ı tercih ediyor?


68

Bir DVCS kullanmanın avantajlarından biri, düzenleme-birleştir-birleştir-birleştir iş akışıdır (genellikle CVCS tarafından uygulanan düzenleme-birleştir-birleştirmeyle ). Her benzersiz değişikliğin, birimlerden bağımsız olarak depoya kaydedilmesine izin vermek, DAG'ın projenin gerçek soyağacını doğru şekilde yansıtmasını sağlar .

Neden bu kadar çok web sitesi "birleşme komisyonlarından kaçınmak" isteğinden bahsediyor? Birleştirme öncesi veya yeniden birleştirme sonrası birleştirmeyi birleştirmek, gerilemeleri izole etmeyi, geçmiş değişiklikleri geri almayı vb. Zorlaştırmaz mı?

Açıklama Noktası: Bir DVCS için varsayılan davranış olduğunu birleştirme taahhüt oluşturun. Neden bu kadar çok yer bu birleşme taahhütlerini gizleyen doğrusal bir gelişim tarihi görme arzusundan bahsediyor?


18
Araçlar her zaman doğru anlamıyor. Ve yanlış anladıklarında, oh oğlum, yanlış mı anlıyorlar.
16'da Oded

2
@Oded, otomatik birleştirme işlemlerini mi kastediyorsunuz (tarafından oluşturulanlar gibi git pull)? Bunun neden sorunlu olabileceğini anlayabiliyorum ama sorum bütün birleşme taahhütleriyle ilgili.
Jace Browning

Sık Karşılaşılan Birleştirme Çatışmalarının Sorunlu Bir İşaret Olduğunu Muhtemel Tekrarlama "Birleşmeler ve yeniden düzenlemeler , bir insanın çözmesi gereken doğal çatışmalar için (yani, aynı geliştirici aynı kod satırını değiştiren iki geliştirici için) aynı çatışmalara neden olmalı ..."
gnat

Bir düşünce ben IMO bir cevap aynen uymuyor ki benim cevap yazdıktan sonra vardı: git pull --rebase == svn up(gevşek-eşittir, değil sıkı-eşittir)
Izkata

SourceSafe gibi merkezi bir mağazada, değişiklikler devam eden bir çaba ile kontrol edilmeye devam edecek, ancak istikrarlı bir platoya ulaşıldığında tüm dosyaları belirli bir tarih itibariyle etiketleyeceğiz. O zaman en azından böcekleri böyle bir sürümden önce veya sonra ya da rebase -line ile ilişkilendirebilirsiniz.
Andyz Smith

Yanıtlar:


64

İnsanlar birleştirme işlemlerinden kaçınmak istiyorlar çünkü günlüğü daha güzel yapıyor. Ciddi anlamda. Büyüdükleri merkezileşmiş kütüklere benziyorlar ve yerel olarak tüm gelişimlerini tek bir dalda yapabiliyorlar. Bu estetiğin yanı sıra, “merkezi” sunucudan geçmeden doğrudan bir meslektaşımdan çekmeyi çatışmaya yatkın kılmak gibi, bahsettiğinizlere ek olarak bazı dezavantajlar da yoktur.


5
Sorumu doğru anlayan tek kişi sensin. Daha net hale nasıl getirebilirim?
Jace Browning

12
Belki "Doğrusal bir gelişim tarihinin faydaları nelerdir?"
Karl Bielefeldt

11
“Sık sık, bunu taahhütlerinizin uzak bir dalda - belki de katkıda bulunmaya çalıştığınız ancak sürdürmediğiniz bir projede - temiz bir şekilde uygulandığından emin olmak için yapacaksınız. Bir dalda ve ardından ana projenize yamaları göndermeye hazır olduğunuzda çalışmalarınızı kaynak / ustaya yeniden düzenleyin.Bu şekilde, bakım kuruluşu herhangi bir entegrasyon çalışması yapmak zorunda kalmaz - sadece hızlı ileri veya temiz bir başvuru. " git-scm.com/book/tr/Git-Branching-Rebasing
Andyz Smith

12
Sadece kozmetik gibi görünmesini sağlıyorsunuz, ama aslında pratiktir: lineer bir tarihte neler olup bittiğini anlamak, hatları geçen ve birleştiren karmaşık bir DAG'dan çok daha kolaydır.
Daniel Hershcovich 21:13

20
"Bu estetiğin bir faydası yok" - Bunu bilmiyorum. Geçmişinizde bir devre kartı gibi göründüğünde geçmişinizde neler olup bittiğini anlamak gerçekten zor. (Her birinin kendi şubesi ve iş akışı olan birden fazla ekip üyesi olduğunu varsayarak.)
Archagon

46

İki kelimeyle: git bisect

Doğrusal geçmiş, bir hatanın gerçek kaynağını belirlemenizi sağlar.


Bir örnek. Bu bizim ilk kodumuz:

def bar(arg=None):
    pass

def foo():
    bar()

Şube 1, argartık geçerli olmayan bazı yeniden düzenleme işlemlerini gerçekleştiriyor :

def bar():
    pass

def foo():
    bar()

Şube 2'nin kullanılması gereken yeni bir özelliği var arg:

def bar(arg=None):
    pass

def foo():
    bar(arg=1)

Birleştirme çatışması olmayacak, ancak bir hata ortaya kondu. Neyse ki, bu belirli bir derleme adımda yakalanacak, ama biz her zaman çok şanslı değiliz. Hata, derleme hatası yerine beklenmeyen bir davranış olarak kendini gösterirse, bir veya iki hafta bulamayabiliriz. Bu noktada, git bisectkurtarmaya!

Kahretsin. Gördüğü bu:

(master: green)
|             \_________________________
|                \                      \
(master: green)  (branch 1: green)     (branch 2: green)
|                 |                     |
|                 |                     |
(master/merge commit: green)            |
|                         ______________/
|                        /
(master/merge commit: red)
|
...days pass...
|
(master: red)

Bu yüzden git bisect, yapıyı bozan taahhüdü bulmaya gönderdiğimizde , bir birleştirme taahhüdünü belirleyecektir. Peki, bu biraz yardımcı olur, ama aslında tek bir tane değil, bir paket paketine işaret ediyor. Tüm atalar yeşil. Öte yandan, rebasing ile doğrusal bir tarih elde edersiniz:

(master: green)
|
(master: green)
|
(all branch 1 commits: green)
|
(some branch 2 commits: green)
|
(branch 2 commit: red)
|
(remaining branch 2 commits: red)
|
...days pass...
|
(master: still red)

Şimdi, git bisectyapıyı bozan kesin özellik taahhüdüne işaret edecek. İdeal olarak, taahhüt mesajı başka bir refraktör yapmak ve hatayı derhal düzeltmek için yeterince iyi tasarlanmış olanı açıklayacaktır.

Bu etki yalnızca büyük projelerdeki bakımcılar tüm kodu yazmadığında birleştirilir, bu nedenle verilen herhangi bir taahhüdün neden yapıldığını / her dalın ne için olduğunu mutlaka hatırlamazlar. Bu yüzden kesin taahhüdün tam olarak belirlenmesi (ve çevresindeki komisyonları inceleyebilmenin) büyük bir yardımdır.


Bu, (şu anda) hala birleştirmeyi tercih ettiğimi söyledi. Serbest bırakma dalına yeniden basmak git bisect, günlük işler için gerçek geçmişi korurken, kullanım için doğrusal geçmişinizi verecektir .


2
Bu açıklama için teşekkürler. Neden hala birleşmeyi tercih ettiğinizi genişletebilir misiniz? Birçok insanın çoğu durumda yeniden doğmayı birleştirmeyi tercih ettiğini biliyorum, ancak nedenini asla anlayamadım.
Philip

@Philip Bunu yapmakta tereddüt ediyorum, çünkü sadece birkaç aydır küçük kişisel projelerde asla bir takımda kullanmamıştım. Ancak son zamanlarda yaptığım şeyleri takip ederken, şubeler arasındaki taahhüt akışını görebilmek gitk --allson derece yararlı (özellikle de herhangi bir zamanda 3-şube şubelerim olduğundan ve her gün arasında bulunduğum ruh halime bağlı olarak değiştiğimde) zaman).
Izkata

16
Ama birleştirme sorun, yani sonuçta bir birleştirme taahhüdü istiyorsunuzbisect . Daha derin kazmak istiyorsanız , bireyi bir blameveya başka bir taahhütle sonuçlandırmak yeterince kolaydır bisect. Doğrusal bir tarihçeyle, birleştirme kitaptan yapılır, böylece artık kötü bir birleşmenin sorun olduğunu söyleyemezsiniz. Sadece var olmayan bir argüman kullanan bir aptal gibi gözüküyor, özellikle argüman önceki birkaç işlemden çıkarılmışsa. Bunu neden yaptığını anlamaya çalışmak , tarihi mahvederken çok daha zor.
Karl Bielefeldt

1
Gerçekten bu cevaba katılmıyorum. Yeniden doğurma, zaman zaman ihanetin faydasını yok eder. Bir rebase'in başkanının komisyonları hariç, bir rebase'den alınan komisyonlar çalıştırılamayabilir. Örnek: A'da dallandınız ve B, C, D'yi yaptınız, biri E'ye bastı. Siz B ve C'siniz ve çalışıyorsunuz ancak E üzerine yeniden doğuyorsunuz, B ve C siz yenilmezsiniz ya da koşuyorsunuz ve çalışmıyorsunuz. En iyi durumda pes olduğunu, en kötü durumda sen gerçekte D. olduğunda B veya C sorunu içeriyor düşünüyorum
Lan

4
@ Izkata Neden bisect kullanıyorsunuz? Çünkü hatalar / hatalar olur. Bu alçakgönüllü bir gerçeklik. Belki de "fareyi sola sürüklemek" daha önce otomatik / manuel test listesinin bir parçası değildi ve şimdi bu özelliğin bozulduğunu fark ettik ancak eskiden çalıştığını biliyoruz.
Lan,

17

Kısacası, birleşme çoğu zaman bir şeyin yanlış gitmesi için başka bir yer olduğu için ve insanların bir kez daha onunla uğraşmaktan çok korkması için sadece bir kez yanlış gitmesi gerekir (eğer bir kez iki kez utangaç olunursa).

Diyelim ki yeni bir Hesap Yönetimi Ekranı üzerinde çalışıyoruz ve Yeni Hesap iş akışında keşfedilen bir hata olduğu ortaya çıktı. Tamam, iki ayrı yol izliyoruz - Hesap Yönetimini tamamladınız ve hatayı Yeni Hesaplar ile düzelttim. İkimiz de hesaplarla uğraştığımız için, çok benzer bir kodla çalışıyoruz - belki de aynı kod parçalarını ayarlamak zorunda kaldık.

Şimdi, şu anda yazılımın iki farklı fakat tamamen çalışan sürümü var. Her ikimiz de değişikliklerimizle ilgili bir taahhütte bulunduk, her ikimiz de kodumuzu dürüstçe test ettik ve bağımsız olarak harika bir iş yaptığımıza eminiz. Şimdi ne olacak?

Birleşme zamanı, ama ... bok, şimdi ne olacak? İki çalışan yazılım grubundan, Hesap Yönetiminizin çalışmadığı ve Yeni Hesapların kırıldığı ve eski hatanın hala orada olup olmadığını bile bilmediğim, birleştirilmiş, birleşmiş, korkunç kırılmış yeni buggy yazılımına geçebiliriz. .

Belki yazılım akıllıydı ve bir çatışma olduğunu söyledi ve rehberlik etmekte ısrar etti. Kahretsin - Bunu yapmak için oturuyorum ve görüyorum ki hemen anlamadığım bazı karmaşık kodlar eklediniz. Yaptığım değişikliklerle çakıştığını düşünüyorum ... Size soruyorum ve bir dakikanızı aldığınızda kontrol edip anlamadığınız kodumu görüyorsunuz. İkimizden birinin veya ikimizin oturmak için zaman ayırması, uygun bir birleştirme yapması ve muhtemelen kırılmadığımızdan emin olmak için tüm tehlikeyi yeniden test etmesi gerekiyor.

Bu arada diğer 8 adam da sadistler gibi kod işliyorlar, birkaç küçük hata düzeltdim ve bir birleşme çatışması olduğunu bilmeden önce bunları gönderdim, ve kesinlikle bir ara vermek için iyi bir zaman gibi görünüyor. öğleden sonra için izinli değil veya bir toplantıda ya da her neyse sıkışmış. Belki de sadece tatile çıkmalıyım. Veya kariyerlerini değiştir.

Ve böylece, bu kabustan kaçmak için bazı insanlar bağlılıktan çok korkmuş hale geldiler (başka ne yeni, gece?). Bunun gibi senaryolarda doğal olarak riskten kaçınıyoruz - eğer emeceğimizi ve bir şekilde batırmayacağımızı düşünmediğimiz sürece, bu durumda insanlar umursamaz bir şekilde terk etme ile hareket etmeye başlar. iç çekmek

Al işte ozaman, buyur. Evet, modern sistemler bu acıyı hafifletmek için tasarlandı ve bunların kolayca geri çekilebilmesi ve yeniden doldurup debase ve freebase ve hanglide ve bunların hepsini alabilmesi gerekiyordu.

Ama hepsi daha iş, ve sadece mikrodalga fırının üzerindeki düğmeye basmak ve bir çatal bulmak için zamanımızdan önce 4 çeşit bir yemek yapmak istiyoruz ve hepsi çok dolmaz bir şekilde doluyor - kod iş, verimli, anlamlı, ancak incelikle bir birleştirme iş sadece sayılmaz.

Programcılar, bir kural olarak, harika bir çalışma hafızası geliştirmeli ve ardından tüm önemsiz ve değişken isimleri ve problemi tamamladıktan hemen sonra kapsamayı ve bir birleştirme çatışmasını ele almayı (veya daha kötüsü, yanlış ele alınan birleştirme) ölümünüzü hatırlatması için bir davettir.


5
İnanılmaz ifadeler efendim!
Southpaw Hare

10
Bu, insanların neden birleşmekten korktuğunu, birleştirme işlemlerinin pek çok kişi tarafından kötü kabul edilmediğini gösteriyor.
Jay

23
Bu sorunun cevabı, bunun bir yeniden ödeme için hala geçerli olması . Ne de olsa, bir rebase hala değiştirilmiş olan bir kod satırını değiştirdiğiniz bir birleştirme yapıyor. Bunun, sorunun ifade edildiği şekilde bir sorun olduğunu düşünüyorum.
deworde

1
Bu cevabı reddettim, çünkü hâlâ anlamlı olduğu için, meselenin ötesinde, imho.
Eugene

5
Bu, yeniden birleştirme vs birleştirme birleştirme hiç görünmüyor.
Andyz Smith

5

Yeniden düzenleme, değişiklikleri başlangıç ​​çizgisine geri itme işlemini basitleştiren hareketli bir dallanma noktası sağlar. Bu, uzun süredir çalışan bir şubeye yerel bir değişiklikmiş gibi davranmanıza olanak tanır. Yeniden yapılanma olmadan dallar, taban çizgisinden, taban çizgisine birleştirilen değişikliklere dahil edilecek değişiklikleri biriktirir.

Birleştirme, taban çizginizi orijinal dal noktasında bırakır. Dallanmış olduğunuz çizgiden birkaç hafta sonra yapılacak değişiklikleri birleştirirseniz, şimdi şubenizden birçok şey sizin temelinizde olacak şekilde birçok değişikliğe sahipsiniz. Bu, şubenizdeki değişikliklerinizi tanımlamayı zorlaştırır. Değişiklikleri taban çizgisine geri itmek, değişikliklerinizle ilgili olmayan ihtilaflara neden olabilir. Uyuşmazlık durumunda, tutarsız değişiklikler yapmak mümkündür. Devam eden birleşmelerin yönetimi gayret gösterir ve değişiklikleri kaybetmek kolaydır.

Rebase şube noktanızı taban çizginizdeki en son revizyona taşır. Karşılaştığınız herhangi bir ihtilaf, yalnızca değişiklikleriniz için geçerli olacaktır. Değişiklikleri zorlamak çok daha kolay. Çatışmalar yerel bir şubede ek bir yeniden ödeme yaparak ele alınmaktadır. Çelişkili itme durumunda, değişikliklerini iten son kişinin değişikliği ile ilgili sorunu çözmesi gerekecektir.


1
böylece tüm öyle çünkü onlar 'yanlış şey' olarak kabul edilir bir düzeye Yeni değişiklikleri indirgemek olduğunu onlar sadece değişiklik . Tüm eski değişiklikler birleştirme işlemine dahil edilirse, tüm değişiklikler bugün 'doğru şey' olup olmadıklarına ilişkin olarak, temel düzeydedir.
Andyz Smith

@AndyzSmith, yeni değişiklikleri yanlış olanı düşünmezdim . Neyin değişmekte olduğunu ve itilmesi gerektiğini belirlemeye çalışırken, doğru şeylerdir . Yeniden doğduktan sonra, eski değişiklikleri görmezden gelebilirsiniz.
BillThor

doğru, yani taban hattınızın ne olduğundan emin değilseniz, yani, birleştirilmeye hazır olanı değiştirdiyseniz, 'doğru şey' olup olmadığını yeniden deneyin.
Andyz Smith

Ve eğer birinden bir değişiklik zorlarsanız, ve fonksiyon prototipi mevcut bir prototip ile eşleşmediğinden yapıyı bozarsa, anında, yeniden yapılanma nedeniyle, yeni adamın yanlış olduğunu biliyorsunuz. Belki de yeni adamın doğru prototip olduğunu tahmin etmenize gerek yoktur ve daha önce yeniden yapılandırılmamış, gerçekleştirilmemiş changet değişikliklerinin yanlış prototipte olanlardır.
Andyz Smith

4

Otomatikleştirilmiş araçlar, birleştirme kodunun derlenip çalıştırılacağından emin olmada daha iyi hale geliyor, böylece sözdizimsel çakışmaları önlüyor , ancak birleştirme tarafından ortaya konabilecek mantıksal çatışmaların bulunmadığını garanti edemiyorlar . Bu nedenle, 'başarılı' birleştirme, gerçekte hiçbir şeyi garanti etmediğinde ve tüm testlerinizi yinelemeniz gerektiğinde, size yanlış bir güven duygusu verir.

Dallanma ve birleşme ile ilgili asıl sorun, gördüğüm gibi, meşhur kutuyu yoldan aşağı atmasıdır. Bir haftalığına "Sadece kendi küçük dünyamda çalışacağım" demenizi ve sonradan ortaya çıkan sorunları çözmenizi sağlar. Fakat böcekleri tamir etmek, taze olduklarında her zaman daha hızlı / daha ucuzdur. Tüm kod dalları birleştirilmeye başladığında, yapılan şeylerin bazılarını zaten unutabilirsiniz.

Yukarıda belirtilen iki problemi bir arada ele alın ve kendinizi, aynı gelişimi gerçekleştiren ve aktif gelişimi biraz daha yavaşlatsa bile, ortaya çıkan çatışmaları sürekli olarak çözmenin daha kolay ve daha kolay olduğu bir durumda bulabilirsiniz.


4
Bu, insanların neden birleşmekten korktuğunu, birleştirme işlemlerinin pek çok kişi tarafından kötü kabul edilmediğini gösteriyor.
Jay

Yani, Bahsettiğiniz bu bagaj, yeniden kazanıma mı dayanıyor? Lütfen açıklayın.
Andyz Smith

@AndyzSmith "trunk", svn'nin git'in "master" şubesine eşdeğer bir terimdir
Izkata

@Izkata yani bu cevap o zaman birleştirme veya rebase kullanılmaması savunucusu?
Andyz Smith 26:13

@AndyzSmith Evet, ben de öyle okudum. Ve ben buna katılmıyorum; Önerilen şekilde 7 geliştirici olan bir ekip üzerinde çalıştıktan sonra bunu önermiyorum. Özellik dallarını yaptığımızdan daha fazla kullanmalıydık, ancak birçoğu birleşmekten korkuyor (BrianDHall'ın cevabına girerken).
Izkata

0

Diğer bir önemli nokta şudur: Yeniden doğurma ile, serbest bırakma şubemdeki bir özelliği kolayca kiraz olarak seçebilir veya geri alabilirim.


1
Bu konuda ayrıntılı?
Akavall

Tabii :-) Git akışında, düzenli olarak yeni sürüm dalları oluştururuz. Oluşturulduktan sonra, geliştirme dalında bir hata giderilirse, git cherry-pick -x <commit>yayın dalına uygulamak için kullanırız. Veya, sürüm için bir şeyi geri almak isteyebiliriz git revert <commit>. Eğer <commit>bir birleştirme, bu kıllı alır. Bu ise biliyorum, ama yapmak kolay değil kadarıyla mümkün. Rebase kullanırken, her 'birleştirme' dev ama düzenli bir taahhüt, kolayca taşınabilir ve geri alınabilir.
Bruno Schäpper 20:18

0

Yanıtların hiçbirinde üç şey söylenmedi:

  • Dalın içine dalmak:

    • Bir daldaki keyfi bir komisyon çifti arasında fark, birleştirme kararları olduğunda oldukça zorlaşır.
  • Bir seferde bir öğeyi birleştirmek:

    • İki dal arasındaki farkı çözdüğünüzde, genellikle bir kerede bir birleştirme olur ve belirli bir taahhüdün içeriğinden bağımsız olarak yaptığınız birleştirme çatışmaları, çatışmanın hangi özel taahhüdünden sorumluydu. Yeniden fiyatlandırırsanız, yeniden fiyat çatışmanın gerçekleştiği noktada durur ve bu bağlamda çözmenize izin verir.
  • İtme işleminden önce temizleme:

    • Bir hata yaptıysanız, daha sonra düzeltmeniz gereken bir taahhütte bulunduysanız, ittirmediyseniz etkileşimli rebase, birleştirme / bölme / değiştirme / taşıma işlemlerini birleştirmenize izin verir. Birleştirdiyseniz, yine de bunu yapabilseniz de, bir birleştirme sınırları boyunca birleştirmek / bölmek / değiştirmek / taşımak istemeniz çok zor hale gelir.
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.