Adlandırılmış Dallar ve Birden Çok Depo


130

Şu anda nispeten büyük bir kod tabanında yıkımı kullanıyoruz. Her sürümün kendi dalı olur ve düzeltmeler gövdeye karşı gerçekleştirilir ve kullanılarak sürüm dallarına taşınır.svnmerge.py

Daha iyi kaynak kontrolüne geçme zamanının geldiğine inanıyorum ve bir süredir Mercurial ile oynuyorum.

Mercurial kullanarak böyle bir sürüm yapısını yönetme konusunda iki düşünce ekolü var gibi görünüyor. Ya her sürüm kendi deposunu alır ve sürüm dalına karşı düzeltmeler yapılır ve ana dala (ve diğer yeni sürüm dallarına) gönderilir YA DA tek bir depodaki adlandırılmış dalları kullanarak (veya birden çok eşleşen kopya).

Her iki durumda da, salım dallarına dahil etmek için kirazdan kirazdan yapılan değişikliklere nakil gibi bir şey kullanıyor olabilirim.

Sana soruyorum; her bir yaklaşımın göreceli avantajları nelerdir?

Yanıtlar:


129

En büyük fark, şube adlarının tarihe nasıl kaydedildiğidir. Adlı dalları ile şube adı olan gömülü her Değişiklik listesi ve böylece tarihin değişmez bir parçası haline gelecektir. Klonlarla, belirli bir değişiklik setinin nereden geldiğine dair kalıcı bir kayıt olmayacaktır .

Bu, klonların bir dal adını kaydetmek istemediğiniz hızlı deneyler için harika olduğu ve adlandırılmış dalların uzun vadeli dallar için iyi olduğu anlamına gelir ("1.x", "2.x" ve benzeri).

Ayrıca, Mercurial'de tek bir deponun birden çok hafif dalı kolayca barındırabileceğini unutmayın. Bu tür arşiv içi şubeler, kolayca tekrar bulabilmeniz için yer imlerine eklenebilir. Diyelim ki şirket deposunu şöyle göründüğünde klonladınız:

[a] --- [b]

Kesiyorsunuz ve yapıyorsunuz [x]ve [y]:

[a] --- [b] --- [x] --- [y]

Ortalama birisi koyar iken [c]ve [d]depoya, bu nedenle çektiğinde böyle bir geçmişi grafiği olsun:

            [x] --- [y]
           /
[a] --- [b] --- [c] --- [d]

Burada tek bir depoda iki başlık var. Çalışan kopyanız her zaman tek bir değişiklik setini yansıtır, sözde çalışma kopyası ana değişiklik seti. Bunu şununla kontrol edin:

% hg parents

Diyelim ki raporlar [y]. Kafaları görebilirsin

% hg heads

ve bu rapor edecek [y]ve [d]. Deponuzu temiz bir kullanıma güncellemek istiyorsanız [d], yapmanız gereken ( [d]revizyon numarası ile değiştirin [d]):

% hg update --clean [d]

Daha sonra o hg parentsraporu göreceksiniz [d]. Bu, sonraki taahhüdünüzün [d]ebeveyn olarak olacağı anlamına gelir . Böylece, ana dalda fark ettiğiniz bir hatayı düzeltebilir ve değişiklik kümesi oluşturabilirsiniz [e]:

            [x] --- [y]
           /
[a] - [b] - [c] - [d] - [e]

[e]Yalnızca değişiklik kümesini göndermek için yapmanız gereken

% hg push -r [e]

[e]değişiklik kümesi karması nerede . Varsayılan olarak hg pushbasitçe depoları karşılaştırmak ve göreceksiniz [x], [y]ve [e]eksik, ancak paylaşımına istemeyebilirsiniz [x]ve [y]henüz.

Hata düzeltmesi sizi de etkiliyorsa, bunu özellik dalınızla birleştirmek istersiniz:

% hg update [y]
% hg merge

Bu, depo grafiğinizi şöyle bırakacaktır:

            [x] --- [y] ----------- [z]
           / /
[a] - [b] - [c] - [d] - [e]

ve [z]arasındaki birleştirme nerede . Ayrıca dalı atmayı da tercih edebilirdin:[y][e]

% hg strip [x]

Bu hikayedeki ana noktam şudur: Tek bir klon, birçok geliştirme yolunu kolayca temsil edebilir. Bu, herhangi bir uzantı kullanmadan "düz hg" için her zaman doğru olmuştur. İmleri uzatma olsa harika bir yardımcı. Değişiklik ayarlarına isimler (yer imleri) atamanıza izin verecektir. Yukarıdaki durumda, geliştirme başlığınızda ve yukarı akış başında bir yer imi isteyeceksiniz. Mercurial 1.6 ile yer imleri itilip çekilebilir ve Mercurial 1.8'de yerleşik bir özellik haline gelmiştir.

İki klon yapmayı seçmiş olsaydınız, geliştirme klonunuz yaptıktan sonra şöyle görünürdü [x]ve [y]:

[a] --- [b] --- [x] --- [y]

Ve yukarı akış klonunuz şunları içerecektir:

[a] --- [b] --- [c] --- [d]

Şimdi hatayı fark edersiniz ve düzeltirsiniz. hg updateYukarı akış klonu kullanıma hazır olduğundan burada zorunda değilsiniz . Taahhüt edersiniz ve yaratırsınız [e]:

[a] --- [b] --- [c] --- [d] --- [e]

Hata düzeltmeyi geliştirme klonunuza dahil etmek için oraya çekin:

[a] --- [b] --- [x] --- [y]
           \
            [c] --- [d] --- [e]

ve birleştir:

[a] - [b] - [x] - [y] - [z]
           \ /
            [c] --- [d] --- [e]

Grafik farklı görünebilir, ancak aynı yapıya sahiptir ve sonuç aynıdır. Klonları kullanarak biraz daha az zihinsel defter tutma yapmanız gerekiyordu.

Adlandırılmış dallar, oldukça isteğe bağlı oldukları için burada gerçekten resmin içine girmedi. Mercurial, adlandırılmış dalları kullanmaya geçmeden önce yıllarca iki klon kullanılarak geliştirildi. 'Varsayılan' şubeye ek olarak 'kararlı' adlı bir şubeyi sürdürüyoruz ve sürümlerimizi 'kararlı' şubeye göre yapıyoruz. Önerilen iş akışının açıklaması için wikideki standart dallanma sayfasına bakın .


1
Eğer değişiklik seti farklı bir kullanıcıdan geldiyse, bu kaydedilmiş olurdu, bu yüzden klon kullanmak kötü bir şey değildir. Yeni bir Özelliği zorlarken, bunu ayrı bir depodan yaptığınızı bilmek çoğu zaman ilginç değildir. Ayrıca, size yalnızca yerel bir şube veren yerel bir şube uzantısı da vardır. Depoyu klonlarken kullanışlıdır, yüksek maliyetlerle (zaman / alan) ilişkilidir.
Johannes Rudolph

2
referans: 'klonlar hızlı deneyler için harikadır' - Hayır, değiller! Ya depoda birkaç binlerce dosyanız varsa? Dal değiştirme sadece bir an (<1 saniye) sürerken klonlama yaşları (1 dakikadan fazla herhangi bir zamanda) alacaktır. Hala adlandırılmış dalları kullanmak değişiklik günlüğünü kirletecektir. Çıkmaz bir yol değil mi? Yoksa bir şey mi kaçırıyorum?
seler

Tamam seler; Orijinal argümanında bir değişiklik gibi görünüyor; Klonlar, birden fazla tam kopyanın ek yükünün sizin için önemli olmadığı veya şube başına ayrı yerel çalışma kopyalarının maliyetini azaltmak için hg'nin sembolik bağlantılarını / sabit bağlantılarını kullanabildiğiniz durumlarda iyidir.
Warren P

@seler: Kod bade büyükse klonların kullanışsız olduğu konusunda oldukça haklısınız. Yer imleri o zaman çözümdür.
Martin Geisler

29

Bence tüm tarihi tek bir depoda istiyorsun. Kısa vadeli bir repo üretmek, kısa vadeli deneyler içindir, yayınlar gibi büyük olaylar için değil.

Mercurial'in hayal kırıklıklarından biri, kısa ömürlü bir dal yaratmanın, onunla oynamanın, onu terk etmenin ve çöpü toplamanın kolay bir yolu yok gibi görünmesidir. Şubeler sonsuzdur. Tarihi asla terk etmek istememeyi anlıyorum ama süper ucuz, tek kullanımlık dallar gitgerçekten görmek istediğim bir özellik hg.


20
Böylesi bir özellik dalını çok kolay bir şekilde yapabilirsiniz: dal noktanıza "hg güncellemesi", düzenleyin ve "hg commit". Farklı bir geliştirme hattı yarattınız - yeni taahhütler bu dalı genişletecek. Ondan kurtulmak için "hg clone -r" kullanın veya "hg strip" ile satır içi olarak kaldırın. Bu yüzden lütfen hayal kırıklığına uğramayın veya özellik taleplerinizle birlikte Mercurial posta listelerine gelin.
Martin Geisler

8
İstediğim gibi görünüyor hg strip. Çevrimiçi belgeler neden şubelerin silinemediğini iddia ediyor?
Norman Ramsey

11
Mercurial'in nasıl bir şekilde gitten
Martin Geisler

9
İle adlandırılmış bir şubeyi kapatabilirsiniz hg ci --close-branch.
Andrey Vlasovskikh

3
@Norman Ramsey: İnsanlar şubelerin silinemeyeceğini söylediğinde, değişiklik setlerinde gömülü olan şube adını değiştiremeyeceğiniz anlamına gelir. Bir dalda bir değişiklik bize hayır , bir dalı tanımlar . Farklı bir şubeye "taşımak" istiyorsanız, değişiklik kümesini silmeniz ve farklı bir dal adıyla yeniden oluşturmanız gerekir.
Martin Geisler

14

Sen yapmalıdır hem .

@Norman'dan kabul edilen yanıtla başlayın: Her sürümde bir adlandırılmış dal içeren bir depo kullanın.

Ardından, oluşturmak ve test etmek için sürüm dalı başına bir klona sahip olun.

Önemli bir not, birden fazla depo kullansanız bile, transplantdeğişiklik kümelerini aralarında taşımak için kullanmaktan kaçınmanız gerektiğidir, çünkü 1) hash'i değiştirir ve 2), yaptığınız değişiklikler arasında çelişkili değişiklikler olduğunda tespit edilmesi çok zor olan hatalar ortaya çıkarabilir. nakli ve hedef dal. Bunun yerine normal birleştirme yapmak istersiniz (ve önceden birleştirmeden: birleştirmeyi her zaman görsel olarak inceleyin), bu da @mg'nin cevabının sonunda söylediği şeyle sonuçlanacaktır:

Grafik farklı görünebilir, ancak aynı yapıya sahiptir ve sonuç aynıdır.

Daha ayrıntılı olarak, eğer birden fazla depo kullanıyorsanız, "ana" depo (veya varsayılan, ana, geliştirme, her neyse) TÜM depolardaki TÜM değişiklik kümelerini içerir . Her yayın / dal deposu, siz eski bir sürümü geride bırakmak isteyene kadar, tümü bir yöne veya diğerine arka tarafa birleştirilen ana hattaki bir daldır. Bu nedenle, bu ana repo ile adlandırılmış şube şemasındaki tek repo arasındaki tek gerçek fark, şubelerin adlandırılıp adlandırılmamasıdır.

Bu, neden "tek repo ile başla" dediğimi anlamalı. Bu tek depo, herhangi bir sürümdeki herhangi bir değişiklik setini aramanız gereken tek yerdir . Sürüm oluşturma için sürüm dallarında daha fazla değişiklik setini etiketleyebilirsiniz. Kavramsal olarak açık ve basittir ve sistem yöneticisini daha basit hale getirir, çünkü her zaman kesinlikle mevcut ve kurtarılabilir olması gereken tek şey budur.

Ancak yine de, derlemeniz ve test etmeniz gereken dal / sürüm başına bir klon tutmanız gerekir. Yapabildiğiniz kadar önemsizdir hg clone <main repo>#<branch> <branch repo>ve daha sonra hg pullşubede repo, o dalda yalnızca yeni değişiklik kümeleri çekecektir (artı, birleştirilen önceki dallardaki ata değişiklikleri).

Bu kurulum, tek çekicinin linux kernel commit modeline en iyi şekilde uyar (Lord Linus gibi davranmak iyi hissettirmiyor mu? Şirketimizde rol entegratörü diyoruz ), çünkü ana repo, geliştiricilerin klonlaması gereken tek şey ve çektirmenin içeri çekilmesi gerekiyor. Şube havuzlarının bakımı yalnızca sürüm yönetimi içindir ve tamamen otomatikleştirilebilir. Geliştiricilerin hiçbir zaman şube depolarından çekmesi / aktarması gerekmez.


İşte bu kurulum için yeniden yapılandırılan @ mg örneği. Başlangıç ​​noktası:

[a] - [b]

Alfa sürümüne geldiğinizde yayın sürümü için "1.0" deyin. Üzerinde hata düzeltmeleri yapın:

[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

(1.0)adlandırılmış dal, taahhüt edene kadar mevcut olmadığından gerçek bir değişiklik kümesi değildir. (Adlandırılmış dalların uygun şekilde oluşturulduğundan emin olmak için etiket eklemek gibi önemsiz bir işlem yapabilirsiniz.)

Birleştirme [m1], bu kurulumun anahtarıdır. Sınırsız sayıda başlığın olabileceği bir geliştirici havuzunun aksine, ana deponuzda birden fazla başlığa sahip olmak istemezsiniz (daha önce belirtildiği gibi eski, ölü sürüm dalı hariç). Bu nedenle, sürüm dallarında yeni değişiklik kümeleriniz olduğunda, bunları hemen varsayılan dalda (veya daha sonraki bir sürüm dalında) yeniden birleştirmeniz gerekir. Bu, bir sürümdeki herhangi bir hata düzeltmesinin sonraki tüm sürümlere de dahil edilmesini garanti eder.

Bu arada, temerrüt dalındaki gelişmeler bir sonraki sürüme doğru devam ediyor:

          ------- [c] - [d]
         /
[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

Ve her zamanki gibi, iki kafayı varsayılan dalda birleştirmeniz gerekir:

          ------- [c] - [d] -------
         /                         \
[a] - [b] ------------------ [m1] - [m2]
         \                 /
          (1.0) - [x] - [y]

Ve bu 1.0 dal klonudur:

[a] - [b] - (1.0) - [x] - [y]

Şimdi bir sonraki sürüm dalını eklemek için bir alıştırma. Eğer 2.0 ise, o zaman kesinlikle varsayılan olarak dallanacaktır. 1.1 ise, 1.0'ı veya varsayılanı kapatmayı seçebilirsiniz. Ne olursa olsun, 1.0'daki herhangi bir yeni değişiklik kümesi önce bir sonraki dala, sonra da varsayılana birleştirilmelidir. Çatışma yoksa bu otomatik olarak yapılabilir ve yalnızca boş bir birleştirme ile sonuçlanır.


Umarım örnek daha önceki noktalarımı netleştirir. Özetle, bu yaklaşımın avantajları:

  1. Tüm değişiklik kümesini ve sürüm geçmişini içeren tek yetkili depo.
  2. Açık ve basitleştirilmiş sürüm yönetimi.
  3. Geliştiriciler ve entegratör için açık ve basitleştirilmiş iş akışı.
  4. İş akışı yinelemelerini (kod incelemeleri) ve otomasyonu (otomatik boş birleştirme) kolaylaştırın.

UPDATE hg bunu kendisi yapar : ana repo varsayılan ve sabit dalları içerir ve kararlı repo kararlı dal klonudur. Ancak, kararlı daldaki sürüm etiketleri sürüm yönetimi amaçları için yeterince iyi olduğundan sürümlü dal kullanmaz.


5

Bildiğim kadarıyla en büyük fark, daha önce belirttiğiniz bir şey: dallanmış isimli, tek bir depodadır. Adlandırılmış dallarda her şey tek bir yerde bulunur. Ayrı depolar daha küçüktür ve taşınması kolaydır. Bu konuda iki düşünce ekolünün olmasının nedeni, açık bir kazanan olmamasıdır. Hangi tarafın argümanları size en mantıklı geliyorsa, muhtemelen gitmeniz gereken konudur, çünkü muhtemelen onların ortamı sizinkine en çok benzemektedir.


2

Mevcut duruma, örneğin bir özelliğin / yeniden tasarımın boyutuna bağlı olarak açıkça pragmatik bir karar olduğunu düşünüyorum. Çatalların, ihmal edilebilir teknik ek yüklerle yeteneklerini kanıtlayarak geliştirici ekibine katılmaları için henüz taahhütte bulunmayan katılımcılar için gerçekten iyi olduğunu düşünüyorum.


0

Sürümler için adlandırılmış şubeleri kullanmamanızı gerçekten tavsiye ederim. Etiketler gerçekten bunun için var. Adlandırılmış dallar, bir stabledal gibi uzun süreli sapmalar içindir .

Öyleyse neden sadece etiketleri kullanmıyoruz? Temel bir örnek:

  • Geliştirme tek bir dalda gerçekleşir
  • Bir sürüm oluşturulduğunda, onu uygun şekilde etiketlersiniz
  • Gelişim oradan devam ediyor
  • Belirli bir sürümde düzeltmeniz gereken (veya her neyse) bazı hatalarınız varsa, sadece etiketini güncelleyin, değişikliklerinizi yapın ve taahhüt edin

Bu, defaultdalda yeni, isimsiz bir kafa , yani. anonim bir şube, hg'de gayet iyi. Daha sonra herhangi bir noktada hata düzeltme işlemlerini ana geliştirme yoluna geri birleştirebilirsiniz. Adlandırılmış şubelere gerek yok.


Bu büyük ölçüde sürecinize bağlıdır. Örneğin bir web uygulaması, kararlı / test / devel şube hiyerarşisiyle iyi çalışır. Masaüstü yazılımı oluştururken, genellikle bir geliştirme şubemiz (varsayılan) ve bakımda bir ila üç (!) Farklı şubemiz vardır. Bir şubeyi ne zaman tekrar ziyaret etmemiz gerekebileceğini tahmin etmek zordur ve bir şubenin majör.minor bir versiyonu izlemesine dair belli bir zarafet vardır.
James Emerton
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.