Git ve Mercurial - Karşılaştır ve Kontrast


520

Bir süredir kişisel projelerim için yıkımı kullanıyorum.

Git ve Mercurial ve genel olarak DVCS hakkında daha fazla şey duymaya devam ediyorum.

Tüm DVCS olayına bir koşuşturma vermek istiyorum, ancak her iki seçeneğe de aşina değilim.

Mercurial ve Git arasındaki bazı farklar nelerdir?

Not: Hangisinin "en iyi", hatta hangisiyle başlamam gerektiğini bulmaya çalışmıyorum . Esas olarak benzer ve farklı oldukları kilit alanları arıyorum, çünkü uygulama ve felsefe açısından nasıl farklı olduklarını bilmek istiyorum.



Yanıtlar:


451

Feragatname: Git'i kullanıyorum, git posta listesindeki Git geliştirmesini takip ediyorum ve hatta Git'e biraz katkıda bulunuyorum (çoğunlukla gitweb). Mercurial'ı belgelerden ve bazılarını FreeNode üzerindeki #revctrl IRC kanalındaki tartışmalardan biliyorum.

Bu yazı için Mercurial hakkında yardım sağlayan #mercurial IRC kanalında bulunan herkese teşekkürler



özet

Burada Markdown PHPMarkdown / MultiMarkdown / Maruku uzantısında olduğu gibi tablo için bazı sözdizimine sahip olmak güzel olurdu

  • Havuz yapısı: Mercurial, ahtapot birleşmelerine (ikiden fazla ebeveyn ile) veya taahhüt edilmeyen nesneleri etiketlemeye izin vermez.
  • Etiketler: Mercurial, .hgtagshavuz başına etiketler için özel kurallara sahip sürümlenmiş bir dosya kullanır ve ayrıca .hg/localtags; refs/tags/Git'teki etiketler ad alanında bulunan referanslardır ve varsayılan olarak getirme sırasında otomatik olarak izlenir ve açık itme gerektirir.
  • Şubeler: Mercurial'da temel iş akışı anonim kafalara dayanır ; Git adlı hafif dallar kullanır ve uzak depodaki dalları takip eden özel dallara ( uzaktan izleme dalları ) sahiptir.
  • Düzeltme adlandırma ve aralıkları: Mercurial , yerelden depoya revizyon numaraları sağlar ve göreli revizyonları (uçtan, yani geçerli daldan sayma) ve revizyon aralıklarını bu yerel numaralandırmaya dayandırır ; Git, dal ipucuna göre revizyona başvurmak için bir yol sağlar ve revizyon aralıkları topolojiktir (revizyon grafiğine dayalı)
  • Mercurial yeniden adlandırma izlemeyi kullanırken Git dosya yeniden adlarıyla başa çıkmak için yeniden adlandırma algılamasını kullanır
  • Ağ: Mercurial, SSH ve HTTP "akıllı" protokolleri ve statik HTTP protokolünü destekler; modern Git SSH, HTTP ve GIT "akıllı" protokolleri ve HTTP (S) "aptal" protokolünü destekler. Her ikisinin de çevrimdışı taşıma için paket dosyaları desteği vardır.
  • Mercurial uzantıları (eklentileri) ve yerleşik API'yı kullanır; Git'in yazılabilirliği ve yerleşik formatları vardır.

Mercurial'ı Git'ten ayıran birkaç şey var, ancak onları benzer yapan başka şeyler de var. Her iki proje de birbirinden fikir alıyor. Örneğin hg bisectMercurial'daki komut (eski adıyla bisect uzantısı ) Git'tekigit bisect komuttan esinlenirken , fikri git bundleilham kaynağı olmuştur hg bundle.

Depo yapısı, revizyonların saklanması

Git'te nesne veritabanında dört tür nesne vardır: bir dosyanın içeriğini içeren blob nesneleri , dosya adları ve dosya izinlerinin ilgili bölümleri dahil olmak üzere dizin yapısını depolayan hiyerarşik ağaç nesneleri (dosyalar için yürütülebilir izin, sembolik bir bağlantıdır) , yazarlık bilgisi içeren taahhüt nesnesi, bir taahhüt (projenin üst dizininin bir ağaç nesnesi aracılığıyla) ile temsil edilen revizyondaki depo durumunun anlık görüntüsüne işaretçi ve sıfır veya daha fazla üst taahhüte atıflar ve diğer nesnelere referansta bulunabilecek nesneleri etiketleme PGP / GPG kullanılarak imzalanmalıdır.

Git, nesneleri depolamanın iki yolunu kullanır: her nesnenin ayrı bir dosyada saklandığı gevşek biçim (bu dosyalar bir kez yazılır ve hiçbir zaman değiştirilmez) ve birçok nesnenin delta sıkıştırılmış olarak tek bir dosyada depolandığı paketlenmiş biçim. Operasyonların atomikliği, bir nesneye yazıldıktan sonra yeni bir nesneye yapılan referansın (atomik olarak create + rename trick kullanılarak) yazılması gerçeğiyle sağlanır.

Git depoları git gc(disk alanını azaltmak ve performansı artırmak için) düzenli aralıklarla bakım gerektirir , ancak günümüzde Git bunu otomatik olarak yapmaktadır. (Bu yöntem, depoların daha iyi sıkıştırılmasını sağlar.)

Mercurial (anladığım kadarıyla) bir dosyanın geçmişini bir dosya günlüğünde depolar (birlikte, yeniden adlandırma izleme gibi ekstra meta veriler ve bazı yardımcı bilgilerle birlikte); dizin yapısını depolamak için manifest adı verilen düz yapıyı ve değişiklik mesajı (revizyonlar) hakkında bilgi veren ve kaydetme mesajı ve sıfır, bir veya iki üst öğe içeren changelog adı verilen yapıyı kullanır .

Mercurial kullanan işlem dergi operasyonları bölünmezlik sağlamak ve güvenir kısaltılıyor kadar temiz sonra başarısız veya kesintiye operasyona dosyaları. Revloglar yalnızca ektedir.

Git'teki Mercurial'a karşı depo yapısına bakıldığında Git'in daha çok nesne veritabanı (veya içeriğe yönelik bir dosya sistemi) ve Mercurial'ın daha çok geleneksel sabit alan ilişkisel veritabanı gibi olduğunu görebiliriz.

Farklılıklar:
Git'te ağaç nesneleri hiyerarşik bir yapı oluşturur; Mercurial manifest dosyasında düz bir yapıdır. Git blob nesnesinde bir dosyanın içeriğinin bir sürümünü depolar ; Mercurial dosya günlüğünde tek bir dosyanın tüm geçmişini saklar (burada yeniden adlandırmalarla ilgili herhangi bir karışıklığı hesaba katmazsak ). Bu, Git'in Mercurial'dan daha hızlı olacağı farklı operasyon alanları olduğu, diğer tüm şeylerin eşit olduğu (birleştirme veya bir projenin geçmişini gösterme gibi) ve Mercurial'ın Git'ten daha hızlı olacağı (yama uygulamak veya göstermek gibi) alanlar olduğu anlamına gelir. tek bir dosyanın geçmişi).Bu sorun son kullanıcı için önemli olmayabilir.

Mercurial'ın changelog yapısının sabit kayıt yapısı nedeniyle, Mercurial'taki taahhütlerin en fazla iki ebeveyni olabilir ; Git'teki taahhütlerin ikiden fazla ebeveyni olabilir ("ahtapot birleştirme" olarak adlandırılır). (Teoride) ahtapot birleştirmeyi bir dizi iki ebeveynli birleştirmeyle değiştirebilmenize rağmen, Mercurial ve Git depoları arasında dönüştürme yaparken komplikasyonlara neden olabilir.

Bildiğim kadarıyla Mercurial'ın Git'ten ek açıklamalı etiketler (etiket nesneleri) eşdeğeri yok . Ek açıklamalı etiketlerin özel bir örneği işaretli etiketlerdir (PGP / GPG imzalı); Mercurial eşdeğeri, Mercurial ile birlikte dağıtılan GpgExtension kullanılarak yapılabilir . Sen olamaz etiket nesnesi olmayan taahhüt Eğer Git'te yapabileceğiniz gibi Mercurial içinde, ama çok önemli olmadığını, ben (bazı git depoları imzalı etiketleri doğrulamak için kullanılacak kamu PGP anahtarını dağıtmak için etiketli bir damla kullanın) düşünüyorum.

Kaynaklar: şubeler ve etiketler

Git referanslarında (şubeler, uzaktan izleme şubeleri ve etiketler) taahhütlerin DAG'ının dışında (olması gerektiği gibi) bulunur. Ad refs/heads/alanındaki ( yerel şubeler ) başvurular taahhütlere işaret eder ve genellikle "git commit" tarafından güncellenir; dalın ucuna (başına) işaret ediyorlar, bu yüzden böyle bir isim. Ad refs/remotes/<remotename>/alanındaki ( uzaktan izleme dalları ) başvurular taahhütte bulunur, uzak depodaki dalları izler <remotename>ve "git fetch" veya eşdeğeri ile güncelleştirilir. Ad refs/tags/alanındaki ( etiketler ) referanslar genellikle taahhütleri (hafif etiketler) veya etiket nesnelerini (açıklamalı ve imzalı etiketler) gösterir ve değiştirilmesi amaçlanmamıştır.

Etiketler

Mercurial'ta, etiketi kullanarak revizyona kalıcı bir ad verebilirsiniz ; etiketleri yok sayma kalıplarına benzer şekilde saklanır. Global olarak görünen etiketlerin deponuzdaki revizyon kontrollü .hgtagsdosyada saklandığı anlamına gelir . Bunun iki sonucu vardır: birincisi, Mercurial, tüm etiketlerin geçerli listesini almak ve bu dosyayı güncellemek için bu dosya için özel kurallar kullanmalıdır (örneğin, dosyanın şu anda teslim alınmamış sürümünde en son taahhüt edilen sürümünü okur); ikinci olarak, yeni etiketin diğer kullanıcılar / diğer depolar tarafından görülebilmesi için bu dosyada değişiklik yapmanız gerekir (anladığım kadarıyla).

Mercurial ayrıca, başkaları tarafından görülemeyen (ve elbette aktarılamayan) depolanan yerel etiketleri de destekler.hg/localtags

Git'te etiketler, refs/tags/ad alanında depolanan diğer nesnelere (genellikle taahhütte bulunan nesneler etiketlenir) sabit (sabit) olarak adlandırılır . Varsayılan olarak bir düzeltme kümesi getirilirken veya itilirken git, getirilen veya iletilen düzeltmelere işaret eden etiketleri otomatik olarak getirir veya iter. Bununla birlikte, hangi etiketlerin getirildiğini veya aktarıldığını bir ölçüde kontrol edebilirsiniz .

Git, hafif etiketleri (doğrudan taahhütlere işaret eder) ve açıklamalı etiketleri (isteğe bağlı olarak PGP imzasını içeren etiket mesajını içeren etiket nesnelerini işaret ederek, işlenecek noktayı işaret eder), örneğin varsayılan olarak, açıklama yaparken yalnızca açıklamalı etiketleri dikkate alır "git define" komutunu kullanır.

Git Mercurial'ta katı bir yerel etiket eşdeğeri yok. Bununla birlikte git en iyi uygulamalar, hazır değişiklikleri zorladığınız ve başkalarının klonlayıp getirdiği ayrı bir genel çıplak depo kurmanızı önerir. Bu, itmediğiniz etiketlerin (ve dalların) deponuza özel olduğu anlamına gelir. Öte yandan da daha ad başka kullanabilir heads, remotesya da tagsörneğin, local-tagsyerel etiketleri için.

Kişisel görüş: Benim düşünceme göre, etiketler, harici oldukları için revizyon grafiğinin dışında olmalıdır (revizyon grafiğine işaretçilerdir). Etiketler sürümlendirilmemiş, ancak aktarılabilir olmalıdır. Mercurial'ın dosyaları görmezden gelmek içinkine benzer bir mekanizma kullanma seçeneği, .hgtagsözel olarak işlemesi gerektiği anlamına gelir (ağaçtaki dosya aktarılabilir, ancak sıradan sürümdür) veya yalnızca yerel olan ( .hg/localtagssürümlendirilmemiş, aktarılamaz).

Dallar

Git yerel şubesinde (şube ipucu veya şube başı), yeni taahhütlerin büyüyebileceği bir taahhüde adlandırılmış bir referanstır. Şube aynı zamanda aktif gelişim çizgisi anlamına da gelebilir, yani tüm şubelere şube ucundan ulaşılabilir. Yerel şubeler refs/heads/ad alanında bulunur, yani 'master' dalının tam adı 'refs / heads / master' şeklindedir.

Git'teki geçerli şube (kullanıma alınmış şube ve yeni taahhüdün gideceği şube) HEAD ref. HEAD sembolik referans olmaktan ziyade doğrudan bir taahhüdü işaret edebilir; anonim isimsiz bir dalda olmanın bu durumuna müstakil HEAD denir ("git branch" '(şube yok)' da olduğunuzu gösterir).

Mercurial'ta anonim dallar (dal başları) vardır ve bir yer imi kullanılabilir ( yer imi uzantısı aracılığıyla ). Bu tür yer imi dalları tamamen yereldir ve bu adlar (sürüm 1.6'ya kadar) Mercurial kullanılarak devredilemez. .hg/bookmarksDosyayı uzak bir depoya kopyalamak için rsync veya scp kullanabilirsiniz . Ayrıca hg id -r <bookmark> <url>, yer işaretinin geçerli bir ipucunun düzeltme kimliğini almak için de kullanabilirsiniz .

1.6'dan beri yer imleri itilebilir / çekilebilir. BookmarksExtension sayfasında bir bölüm Uzaktan Arşivleri ile Çalışma . Mercurial yer imi adlarının global olması arasında bir fark vardır, Git'teki 'uzak' tanımı da uzak depodaki adlardan yerel uzaktan izleme dallarının adlarına eşlenmesini açıklar ; örneğin refs/heads/*:refs/remotes/origin/*haritalama, 'orijin / master' uzaktan izleme kolundaki ('refs / uzaktan kumandalar / orijin / master') uzak depoda 'master' dalının ('refs / heads / master') durumunu bulabileceği anlamına gelir.

Mercurial ayrıca , dal adının bir taahhüde (bir değişiklik kümesine) gömüldüğü adlandırılmış dallar olarak da adlandırılır . Bu ad globaldir (getirildiğinde aktarılır). Bu dal adları kalıcı olarak değişiklik kümesinin meta verilerinin bir parçası olarak kaydedilir. Modern Mercurial ile "adlandırılmış dal" ı kapatabilir ve dal adını kaydetmeyi durdurabilirsiniz. Bu mekanizmada dalların uçları anında hesaplanır.

Mercurial'ın "adlandırılmış dalları" bence bunun yerine taahhüt etiketleri olarak adlandırılmalıdır , çünkü bunlar budur. "Adlandırılmış dal" ın birden fazla ipucu olabileceği (birden çok çocuksuz işlem) ve ayrıca revizyon grafiğinin birkaç ayrık kısmından oluşabileceği durumlar vardır.

Git'te Mercurial "gömülü dalların" eşdeğeri yoktur; Üstelik Git'in felsefesi, bir şubenin bazı taahhütler içerdiğini söylese de, bir taahhüdün bazı şubelere ait olduğu anlamına gelmez.

Mercurial dokümantasyonunun hala en azından uzun ömürlü dallar (depo iş akışı başına tek dal), yani klonlama ile dallanma için ayrı klonlar (ayrı depolar) kullanmayı önerdiğini unutmayın .

Şube şubeleri

Mercurial varsayılan olarak tüm kafaları iter . Tek bir kolu ( tek kafa ) itmek istiyorsanız, itmek istediğiniz dalın uç revizyonunu belirtmeniz gerekir. Şube ipucunu, revizyon numarasına (yerelden depoya), revizyon tanımlayıcısına, yer imi adına (yerelden depoya, aktarılmaz) veya katıştırılmış dal adına (şube adı verilir) göre belirleyebilirsiniz.

Anladığım kadarıyla, Mercurial parlance'de bazı "adlandırılmış dal" olarak işaretlenmiş taahhütleri içeren bir dizi düzeltmeyi iterseniz, bu "adlandırılmış dal" a ittiğiniz depoda olacaksınız. Bu, bu tür gömülü dalların ("adlandırılmış dallar") adlarının küresel olduğu (verilen havuzun / projenin klonlarına göre ) olduğu anlamına gelir .

Varsayılan olarak ( push.defaultyapılandırma değişkenine tabidir ) "git push" veya "git push < remote >" Git eşleşen dalları iter , yani yalnızca eş değerlerini zaten aktardığınız uzak depoda bulunan yerel şubeler. Sen kullanabilirsiniz --allitmek git-itme ( "git push --all") seçeneği tüm şubeleri siz "<git itme kullanabilirsiniz, uzaktan > < dalı bir zorlamaya>" Verilen tek dalı ve "git itme kullanabilirsiniz < uzaktan > BAŞ" itmek için geçerli dalı .

Yukarıdakilerin tümü, Git'in hangi remote.<remotename>.push değişkenleri yapılandırma değişkenleri aracılığıyla gönderilecek şekilde yapılandırılmadığını varsayar .

Alınan dallar

Not: Burada Git terminolojisini kullanıyorum, burada "getir", bu değişiklikleri yerel çalışmalarla entegre etmeden uzak depodaki değişiklikleri indirmek anlamına gelir . " git fetch" Ve " hg pull" bunu yapar.

Bunu doğru anlarsam, varsayılan olarak Mercurial uzaktaki havuzdaki tüm kafaları alır, ancak " hg pull --rev <rev> <url>" veya " hg pull <url>#<rev>" yoluyla tek dal almak için dal belirtebilirsiniz . Düzeltme tanımlayıcısını, "adlandırılmış dal" adını (değişiklik günlüğüne gömülü dal) veya yer işareti adını kullanarak <rev> belirtebilirsiniz. Ancak yer işareti adı (en azından şu anda) aktarılmaz. Aldığınız tüm "adlandırılmış dallar" revizyonları aktarılacaktır. "hg pull" isimsiz, isimsiz kafa olarak getirdiği dalların ipuçlarını saklar.

Git'te varsayılan olarak ("git clone" tarafından oluşturulan 'orijin' uzaktan kumandası için ve "git remote add" kullanılarak oluşturulan uzaktan kumandalar için) " git fetch" (veya " git fetch <remote>") tüm dalları uzak depodan ( refs/heads/ad alanından) alır ve saklar refs/remotes/ad. Bu, örneğin, 'ana' adlı 'ana' (tam ad: 'refs / heads / master') adlı dalın 'orijin / ana' uzaktan izleme dalı (tam ad: 'refs / uzaktan kumanda / kökenli / ana ').

Git'i kullanarak tek dal getirebilirsiniz git fetch <remote> <branch>- Git, istenen dal (lar) ı Mercurial adsız başlıklarına benzer bir şey olan FETCH_HEAD'de depolar.

Bunlar, güçlü refspec Git sözdiziminin varsayılan durumlarına örnektir : refspecs ile, hangi dalları almak istediğinizi ve nerede depolayacağınızı belirleyebilir ve / veya yapılandırabilirsiniz. Örneğin, varsayılan "tüm dalları getir" durumu "+ refs / heads / *: refs / remotes / origin / *" joker karakter refspec'i ile temsil edilir ve "tek dalı getir", "refs / heads / <branch>:" . Refspec'ler, uzak depodaki dalların (ref) adlarını yerel refs adlarıyla eşlemek için kullanılır. Ancak Git ile etkili bir şekilde çalışabilmek için refspec'leri (çok fazla) bilmeniz gerekmez (çoğunlukla "git remote" komutu sayesinde).

Kişisel görüş: Şahsen Mercurial'daki "adlandırılmış dallar" ın (değişiklik kümesi meta verilerine gömülü dal adları ile) küresel ad alanı ile, özellikle dağıtılmış sürüm kontrol sistemi için yanlış tasarım olduğunu düşünüyorum . Örneğin, hem Alice hem de Bob'un depolarında 'for-joe' adında “adlandırılmış şube” bulunduğunu, ortak hiçbir şeyi olmayan dalları ele alalım. Ancak Joe'nun deposunda bu iki dal tek bir dal olarak kötü muamele görecektir. Böylece bir şekilde şube adı çatışmalarına karşı koruma konvansiyonu buldunuz. Bu, Joe'nun Alice'in depodaki 'for-joe' dalında 'alice / for-joe' ve Bob'dan 'bob / for-joe' olacağı Git ile ilgili bir sorun değildir.

Mercurial'ın "yer imi dalları" şu anda çekirdek dağıtım mekanizmasından yoksundur.

Farklılıklar: James Woodyatt ve Steve Losh'un cevaplarında söylediği
gibi, bu alan Mercurial ve Git arasındaki ana farklılıklardan biridir . Mercurial, varsayılan olarak, terminolojisinde "kafa" olarak adlandırılan anonim hafif kodlayıcılar kullanır. Git, uzak depodaki dalların adlarını uzaktan izleme dallarının adlarıyla eşleştirmek için bilinçli olarak adlandırılan dallar kullanır. Git sizi şubeleri adlandırmaya zorlar (tek isimsiz şube hariç, müstakil HEAD adı verilen durum), ancak bunun konu dalı iş akışı gibi şube ağır iş akışları ile daha iyi çalıştığını, yani tek depo paradigmasındaki birden çok dalın daha iyi çalıştığını düşünüyorum.

Düzeltmeleri adlandırma

Git'te revizyonları adlandırmanın birçok yolu vardır (örneğin git rev-parse kılavuzunda açıklanmıştır):

  • Tam SHA1 nesne adı (40 bayt onaltılık dize) veya depo içinde benzersiz olan bir alt dizesi
  • Sembolik bir ref adı, örneğin 'master' ('master' dalına atıfta bulunur) veya 'v1.5.0' (etikete atıfta bulunur) veya 'orijin / sonraki' (uzaktan izleme dalına atıfta bulunur)
  • ^Düzeltme soneki parametresi, bir taahhüt nesnesinin ilk üst ^nöğesi, bir birleştirme işleminin n. Üst öğesi anlamına gelir. ~nRevizyon parametresine bir sonek , düz birinci ebeveyn satırındaki bir taahhüdün n. Atası anlamına gelir. Bu sonekler, sembolik bir referanstan gelen yolu izleyerek revizyon belirleyici oluşturmak için birleştirilebilir, örn. 'Pu ~ 3 ^ 2 ~ 3'
  • "Git description" çıktısı, yani en yakın etiket, isteğe bağlı olarak bir tire ve bir dizi işlem, ardından bir tire, bir 'g' ve kısaltılmış bir nesne adı, örneğin 'v1.6.5.1-75- g5bf8097' .

Burada belirtilmeyen reflog içeren revizyon belirteçleri de vardır. Git'te her nesne, ister taahhüt, etiket, ağaç veya damla SHA-1 tanımlayıcısına sahiptir; belirtilen revizyonda ağaç (dizin) veya blob (dosya içeriği) anlamına gelen 'next: Documentation' veya 'next: README' gibi özel bir sözdizimi vardır.

Mercurial da adlandırma changesets birçok yolu (anlatıldığı gibi sahip olduğu hg manpage):

  • Düz bir tamsayı revizyon numarası olarak kabul edilir. Revizyon numaralarının verilen depo için yerel olduğunu hatırlamak gerekir ; diğer depolarda farklı olabilirler.
  • Negatif tamsayılar, uçtan sıralı ofsetler olarak muamele edilir; -1, ucu belirtir, -2, uçtan önceki revizyonu gösterir vb. Onlar da depo için yerel .
  • Benzersiz bir düzeltme tanımlayıcısı (40 haneli onaltılık dize) veya benzersiz öneki.
  • Bir etiket adı (verilen düzeltmeyle ilişkili sembolik ad) veya yer işareti adı (uzantıyla: verilen başla ilişkilendirilmiş, depodan yerel olan sembolik ad) veya bir "adlandırılmış dal" (taahhüt etiketi; "adlandırılmış dal" tarafından verilen düzeltme verilen taahhüt etiketi ile tüm taahhütlerin ipucu (çocuksuz taahhüt), birden fazla ipucu varsa en büyük revizyon numarası ile)
  • Ayrılmış ad "ipucu" her zaman en son düzeltmeyi tanımlayan özel bir etikettir.
  • Ayrılmış ad "null" null revizyonu belirtir.
  • Ayrılmış ad "." çalışma dizini üst öğesini gösterir.

Farklılıklar
Yukarıdaki listelerin karşılaştırmasını görebileceğiniz gibi Mercurial, depodan yerel olan revizyon numaralarını sunarken Git gitmez. Öte yandan Mercurial, yalnızca depoya yerel olan (en azından ParentrevspecExtension olmadan ) 'uç' (mevcut dal) 'dan göreli ofsetler sunarken, Git herhangi bir uçtan sonra herhangi bir taahhüt belirtmeye izin verir.

En son revizyon Git'te HEAD ve Mercurial'da "ipucu" olarak adlandırılmıştır; Git'te null revizyon yoktur. Hem Mercurial hem de Git birçok köke sahip olabilir (birden fazla ebeveynsiz taahhüt olabilir; bu genellikle daha önce ayrı projelerin katılmasının sonucudur).

Ayrıca bakınız: Elijah's Blog (newren's) ile ilgili birçok farklı türde revizyon spreyi.

Kişisel görüş: Bence revizyon sayıları abartılıyor (en azından dağıtılmış geliştirme ve / veya doğrusal olmayan / dallanma geçmişi için). Birincisi, dağıtılmış bir sürüm kontrol sistemi için ya depodan yerel olana ya da bazı depolara merkezi bir numaralandırma otoritesi olarak özel bir şekilde muamele edilmeleri gerekir. İkincisi, daha uzun geçmişi olan daha büyük projeler, 5 basamak aralığında revizyon sayısına sahip olabilir, bu nedenle 6-7 karakter revizyon tanımlayıcılarına kısaltılmışlara göre sadece küçük bir avantaj sunarlar ve revizyonlar sadece kısmen sipariş edilirken sıkı sipariş gerektirirler (burada n ve n + 1 revizyonlarının ebeveyn ve çocuk olması gerekmez).

Revizyon aralıkları

Git'te revizyon aralıkları topolojiktir . A..BDoğrusal tarih için A'dan başlayan (ancak A hariç) ve B ile biten (yani aralık aşağıdan açık ) revizyon aralığı anlamına gelen yaygın olarak görülen sözdizimi, ^A Btarih geçişi komutları için hepsi anlamına gelen kısayol ("sözdizimsel şeker") anlamına gelir. A'dan ulaşılabilenler hariç B'den ulaşılabilir. Bu, A'nın A..BB'nin atası olmasa bile aralık davranışının tamamen öngörülebilir (ve oldukça yararlı) olduğu A..Banlamına gelir : o zaman A ve B'nin ortak atalarından gelen revizyon aralığı (birleştirme tabanı) ) B revizyonuna.

Mercurial'da revizyon aralıkları revizyon numaralarının aralığına dayanmaktadır . Aralık, A:Bsözdizimi kullanılarak belirtilir ve Git aralığının aksine kapalı bir aralık görevi görür . Ayrıca B: A aralığı, A: B aralığını ters sırada gösterir, bu Git'te geçerli değildir (ancak A...Bsözdizimi ile ilgili aşağıdaki nota bakın ). Ancak böyle bir basitlik bir fiyatla gelir: revizyon aralığı A: B, sadece A'nın B'nin atası olması veya bunun tersi, yani doğrusal geçmiş ile mantıklıdır; Aksi takdirde (sanırım) aralık öngörülemez ve sonuç havuz için yereldir (revizyon numaraları depo için yerel olduğundan).

Bu, yeni topolojik revizyon aralığına sahip Mercurial 1.6 ile düzeltilmiştir , burada 'A..B' (veya 'A :: B'), hem X'in torunları hem de Y'nin ataları olan değişiklik kümeleri olarak anlaşılmaktadır. , Sanırım, Git'teki '--ancestry-path A..B' ile eşdeğer.

Git'in ayrıca A...Bsimetrik revizyon farkı gösterimi var ; bu A B --not $(git merge-base A B), A veya B'den erişilebilen tüm taahhütlerin, her ikisinden de ulaşılabilen tüm taahhütlerin (ortak atalardan erişilebileceği) hariç tutulması anlamına gelir.

Yeniden adlandırır

Mercurial, dosya adlarıyla başa çıkmak için yeniden adlandırma izlemeyi kullanır . Bu, bir dosyanın yeniden adlandırılmasıyla ilgili bilgilerin işlem sırasında kaydedildiği anlamına gelir; Mercurial'ta bu bilgiler filelog (file revlog) meta verilerindeki "gelişmiş fark" formuna kaydedilir . Bunun sonucu, hg rename/ hg mv... kullanmanız veya hg addremovebenzerlik tabanlı yeniden adlandırma algılaması yapmak için çalıştırmayı hatırlamanız gerektiğidir .

Git, dosya adlarıyla başa çıkmak için yeniden adlandırma algılaması kullanması nedeniyle sürüm kontrol sistemleri arasında benzersizdir . Bu, dosyanın yeniden adlandırıldığı gerçeğinin gerektiği zamanda algılandığı anlamına gelir: birleştirme yaparken veya bir fark gösterilirken (istenirse / yapılandırılırsa). Bunun avantajı, yeniden adlandırma algılama algoritmasının geliştirilebilmesidir ve işlem sırasında donmaz.

Hem Git hem de Mercurial, --followtek bir dosyanın geçmişini gösterirken yeniden adlandırmaları takip etmek için seçenek kullanılmasını gerektirir . Her ikisi de git blame/ içindeki bir dosyanın satır geçmişini gösterirken yeniden adlarını takip edebilir hg annotate.

Git'te git blamekomut, kod hareketi sağlıklı dosya yeniden adının bir parçası olmasa bile, kodu bir dosyadan diğerine taşıyabilir (veya kopyalayabilir). Bildiğim kadarıyla bu özellik Git'e özgüdür (yazma sırasında, Ekim 2009).

Ağ protokolleri

Hem Mercurial hem de Git, depo URL'sinin sadece depoya giden bir dosya sistemi yolu olduğu aynı dosya sistemindeki havuzları alma ve bu dosyalara aktarma desteğine sahiptir. Her ikisinin de paket dosyalarından getirme desteği vardır .

Mercurial SSH ve HTTP protokolleri yoluyla getirme ve gönderme desteği. SSH için hedef makinede erişilebilir bir kabuk hesabına ve yüklü / kullanılabilir hg'nin bir kopyasına ihtiyaç vardır. HTTP erişimi için hg-serveveya Mercurial CGI betiğinin çalışması gerekir ve Mercurial'ın sunucu makinesine yüklenmesi gerekir.

Git, uzak depoya erişmek için kullanılan iki tür protokolü destekler:

  • SSH üzerinden ve özel git: // protokolü (by git-daemon) yoluyla erişimi içeren "akıllı" protokoller , git'in sunucuda kurulu olmasını gerektirir. Bu protokollerdeki değişim, hangi nesnelerin ortak olduğu konusunda müzakere eden istemci ve sunucudan oluşur ve daha sonra bir paket dosyası oluşturur ve gönderir. Modern Git, "akıllı" HTTP protokolü için destek içerir.
  • HTTP ve FTP (yalnızca getirme için) ve HTTPS (WebDAV üzerinden itme için) içeren "dilsiz" protokoller , sunucuda git kurulmasını gerektirmez, ancak havuzun ek bilgi içermesini gerektirir git update-server-info(genellikle bir kancadan çalıştırılır) ). Borsa, müşteriyi bağlı zinciri yürüterek ve gerektiğinde gevşek nesneleri ve paket dosyalarını indiren istemciden oluşur. Dezavantajı, kesinlikle gerekli olandan daha fazla indirmesidir (örneğin, sadece tek bir paket dosyası olduğunda köşe durumunda, sadece birkaç düzeltme getirildiğinde bile tamamen indirilir) ve bitirmek için birçok bağlantı gerektirebilir.

Genişletme: kodlanabilirlik ve uzantılar (eklentiler)

Mercurial, performans için C ile yazılmış bazı temel kodlarla Python'da uygulanır . Ek özellikler eklemenin bir yolu olarak uzantıları (eklentileri) yazmak için API sağlar . "Yer imi dalları" veya revizyonları imzalama gibi bazı işlevler Mercurial ile dağıtılan uzantılarda sağlanır ve açılması gerekir.

Git, C , Perl ve kabuk betiklerinde uygulanır . Git, komut dosyalarında kullanıma uygun birçok düşük düzeyli komut ( tesisat ) sağlar. Yeni özellik sunmanın genel yolu, Perl veya kabuk komut dosyası olarak yazmaktır ve kullanıcı arayüzü stabilize edildiğinde performans, taşınabilirlik ve köşe senaryolarından kaçınan kabuk komut dosyası durumunda (bu yordam yerleşikleştirme olarak adlandırılır) C'de yeniden yazılır .

Git, [depo] biçimlerini ve [ağ] protokollerini temel alır ve bunlara dayanır. Dil bağlamaları yerine Git'in diğer dillerde (kısmi veya tam) yeniden uygulamaları vardır (bunların bazıları kısmen yeniden uygulanır ve kısmen git komutlarının etrafına sarılır): JGit (Java, EGit, Eclipse Git Plugin tarafından kullanılır), Grit (Ruby) , Dulwich (Python), git # (C #).


TL; DR


32
Eklenebilecek olan şey, hg'nin tarih yeniden yazmayı caydırmak için çok uğraşmasıdır (sadece uzantılarla yapılabilir: mq, histedit, rebase), git kutudan çıkar çıkmaz yapar (ve topluluğun bir parçası gibi görünür) hatta teşvik eder).
tonfa

80
Bence "yeniden yazma tarihi" gereksiz yere olumsuz geliyor. Ne ben GIT'de teşvik insanlar yayınlama geçmişi dikkate almaktır. Diğer insanların bu tarihi tüketmesi gerekir. Hiç kimse (siz bile değil) tüm "oops, bir dosyayı unuttum" taahhütlerinizle ilgilenmez. Ayrıca, yeni bir özellik üzerinde çalışırken, yukarı yönlü bir şube izlerken, karşılaştığınız gelen birleştirme serileriyle ilgilenmez. Bu tür şeyler tarihin (ve ilgili araçların) anlaşılmasını çok daha zorlaştırır ve değer vermez.
Dustin

5
@ Jakub: adlandırılmış dallar git'te bulunmayan bir şeydir. Bu sadece cset açıklamasındaki bir alandır (ve tarihin bir parçasıdır, bu yüzden hashleri ​​değiştirmediğiniz sürece değişmezdir). Git dalları gibi bir şey yer işaretleridir ("adlandırılmış kafalar") ancak şu anda uzaktan aktarılamazlar (çekerken uzak yer işaretlerini içe aktarmazsınız). stevelosh.com/blog/entry/2009/8/30/… bunu çok iyi açıklıyor.
tonfa

28
"Mercurial başlangıçta havuz iş akışı başına yalnızca bir dalı destekliyor ve gösteriyor." Oh hayır. Mercurial başlangıçta adlandırılmış dalları desteklemedi , ancak her zaman tek bir repoda kalbinizin istediği kadar anonim şubeye sahip oldunuz. Anonim dallanmayı büyük bir acı haline getiren git ile kontrast yapın . Hemen hemen sahip bitirdiniz şey almak (ve iş çöp toplanan zorunda kalmamak) istiyorsanız her küçük dal için bir isim düşünmek.
Steve Losh

17
@SteveLosh: Mercurial'ta çok sayıda anonim şubeye sahip olmanın iyi bir şey olduğunu düşünüyor görünüyorsun, ama bana göre korkunç görünüyor. Onları nasıl birbirinden ayırıyorsun? Git'teki şubeleri adlandırmanın çok büyük bir zorluk olduğunu düşünüyorsunuz, ancak şubeyi oluşturmak için bir amacınız varsa, hazır bir adınız var. Eğer bir amacınız yoksa, dallamayın. Mercurial'ın burada nasıl bir fayda sağladığını göremiyorum. Sadece acı ve karışıklık görüyorum.
iconoclast

57

Sanırım bu iki videoyu çağırarak bu sistemlerin neye benzediğini veya farklı olduğunu hissedebilirsiniz:

Git'te Linus Torvalds ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Mercurial'da Bryan O'Sullivan ( http://www.youtube.com/watch?v=JExtkqzEoHY )

Her ikisi de tasarımda çok benzer ancak uygulamalarda çok farklı.

Mercurial kullanıyorum. Git'i anladığım kadarıyla, git'in önemli bir yanı farklıdır, dosyaların içeriğini dosyaların yerine izlemesidir. Linus, bir işlevi bir dosyadan diğerine taşırsanız Git'in size bu tek işlevin geçmişini hareket boyunca anlatacağını söyler.

Git'in HTTP üzerinden daha yavaş olduğunu, ancak kendi ağ protokolü ve sunucusu olduğunu da söylüyorlar.

Git, SVN kalın istemci olarak Mercurial'dan daha iyi çalışır. Bir SVN sunucusunu çekebilir ve ona karşı itebilirsiniz. Bu işlev Mercurial'ta hala geliştirilmektedir

Hem Mercurial hem de Git çok güzel web barındırma çözümlerine sahiptir (BitBucket ve GitHub), ancak Google Code yalnızca Mercurial'ı desteklemektedir. Bu arada, hangisini destekleyeceğine karar vermek için yaptıkları Mercurial ve Git'in çok ayrıntılı bir karşılaştırması var ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Çok iyi bilgi var.


8
Google kod sayfasındaki tüm yorumları okumanızı tavsiye ederim. Bilgiler biraz önyargılı ve tecrübelerime uymuyor. Hg'yi seviyorum ve bir yıl kadar yaygın olarak kullandım . Git'i neredeyse münhasıran kullanıyorum. Git yapmayı kolaylaştırıyor ve hg neredeyse imkansız hale getiriyor (bazıları "komplikasyon" ile bunu çağırmak ister) rağmen Temel git temel hg kadar kolaydır.
Dustin

11
Dustin, belki de "git easy, hg o kadar fazla değil" vakalarının bazılarını listeliyor?
Gregg Lind

1
@knittl hayır değil. Temelde git akıllı bir http protokolüne sahip olmadığından (Google ön uçlarının çoğu http tabanlıdır) çünkü dağıtmaları onlar için bir acı olacaktır.
tonfa

2
@tonfa: Git için akıllı HTTP protokolü şu anda geliştirilmektedir (olduğu gibi: git posta listesinde yamalar vardır ve git.git deposunda 'pu' = önerilen güncellemeler dalındadır).
Jakub Narębski

4
Google Code şu an Git'i de destekliyor.
Andrej Kirejeŭ

30

Bir süre önce Mercurial'ın dallanma modelleri hakkında bir blog yazısı yazdım ve git'in dallanma modeli ile karşılaştırmalar ekledim. Belki ilginç bulabilirsiniz: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/


@Steve Losh: Bu blog girişi hakkında (adsız şube aka müstakil HEAD hakkında ve git-fetch bir değil tüm dalları getirme hakkında) yorum yapmak istedim, ancak 500 sunucu hatası aldım.
Jakub Narębski

1
@Jakub Narębski Bahse girerim sorun sizin adınızdaki ASCII olmayan karakterdir. Başka bir sitede aynı sorunla karşılaştığımdan eminim ve Python Askimet'in Unicode'a bağlandığı ortaya çıktı. Bir bakacağım.
Steve Losh

@Steve Losh: Bir bilgi için teşekkürler, adımı "unidecoding" den sonra yorum gönderebildim. Mercurial dallanma çok iyi bir açıklama (ama yine de aşağı olduğunu düşünüyorum ;-))
Jakub Narębski

@SteveLosh Bu cevabı daha eksiksiz bir mercurial incelemesine genişletmenizi tavsiye ederim. Şu anda, en iyi cevap maalesef git için bir reklamdır, çünkü yazarı cıvaları yoğun bir şekilde kullanmadı ve etkili bir şekilde nasıl kullanacağını anlamıyor. Yani, başka bir cevabın, mercurial bakış açısını sağlaması iyi olur.
Warren Dew

25

Her ikisini de oldukça düzenli kullanıyorum. En büyük fonksiyonel fark Git ve Mercurial adının depolarda dallanma şeklidir. Mercurial ile dal isimleri, değişiklik kümeleriyle birlikte klonlanır ve çekilir. Mercurial'ta yeni bir şubeye değişiklik ekleyip başka bir depoya bastığınızda, şube adı aynı anda gönderilir. Bu nedenle, şube adları Mercurial'da daha az veya daha az küreseldir ve yalnızca yerel hafif isimlere sahip olmak için Bookmark uzantısını kullanmanız gerekir (isterseniz; Mercurial, varsayılan olarak, terminolojisinde anonim hafif codelines kullanır. "kafa" denir). Git'te, şube adları ve uzak şubelere yönelik amaçsız eşlemeleri yerel olarak depolanır ve bunları açıkça yönetmeniz gerekir, bu da bunun nasıl yapılacağını bilmek anlamına gelir.

Diğerlerinin burada belirteceği gibi, çok sayıda küçük fark var. Dalları olan şey büyük farklılaştırıcıdır.


2
Mercurial'daki dört dal türü hakkında iyi bir açıklama için bu yazıya da bakın: stevelosh.com/blog/entry/2009/8/30/…
Martin Geisler

19

Git vs. Mercurial'a bir göz atın : Patrick Thomson'un yazdığı blog
yazısına bakın : Git MacGyver , Mercurial James Bond

Bu blog gönderisinin 7 Ağustos 2008'den geldiğini ve her iki SCM'nin de o zamandan beri çok geliştiğini unutmayın.


11

Mercurial neredeyse tamamen python ile yazılmıştır. Git'in çekirdeği C (ve Mercurial'ınkinden daha hızlı olmalıdır) ve sh, perl, tcl ile yazılmış araçlar ve standart GNU araçlarını kullanır. Bu nedenle, tüm bu yardımcı ve tercümanları, bunları içermeyen sisteme (örn. Windows) getirmesi gerekir.

Her iki destek de SVN ile çalışır, ancak AFAIK svn desteği Windows'ta git için kırılmış olsa da (kim bilir sadece şanssız / topal olabilirim). Git ve Mercurial arasında birlikte çalışmayı sağlayan uzantılar da vardır.

Mercurial hoş bir Visual Studio entegrasyonuna sahiptir . En son kontrol ettiğimde Git için eklenti çalışıyordu ama son derece yavaştı.

Temel komut setleri çok benzerdir (init, klon, ekleme, durum, taahhüt, itme, çekme vb.). Yani, temel iş akışı aynı olacaktır. Ayrıca, her ikisi için de TortoiseSVN benzeri bir istemci var.

Mercurial için uzantılar python ile yazılabilir (sürpriz yok!) Ve git için herhangi bir yürütülebilir formda (yürütülebilir ikili, kabuk komut dosyası vb.) Yazılabilir. Bazı uzantılar deli gibi güçlü git bisect.


9
Mercurial çekirdek C de FYI olarak yazılmıştır (ancak muhtemelen git'ten daha küçük bir çekirdektir).
tonfa

1
Git-svn'yi Windows'ta sorunsuz kullanıyorum. Cygwin kullanıyor ( bana sorarsanız git'i Windows kullanmanın tek doğru yolu). Msysgit için konuşamıyorum.
Dan Moulding

@Dan Molding: Evet, msysgit ile ilgili sorunlar yaşadım. Belki cygwin port denemek gerekir (cygwin daha önce kullanma konusunda bazı kötü deneyimlerim vardı, bu yüzden kaçındım). Tavsiyen için teşekkürler!
elder_george

Şahsen cygwin'in kullanıcı verilerini saklamak için kayıt defterine girmesini sevmiyorum. USB anahtarımı çalıştırmak ve USB anahtarımın gidebileceğinden daha hızlı çalıştırmak istediğimde yerel bir c: \ sürücü kopyasını senkronize tutmak PITA. : - /
Chris K

1
Yukarıda bahsedilen Visual Studio için Git eklentisini kullanıyorum ve mevcut sürümün performansı iyi. İşi yapmak için komut satırı araçlarına mermi yapıyor, bu yüzden büyük projelerde performansı önemli ölçüde kaybedeceğini düşünmüyorum.
Stuart Ellis

11

İyi bir Windows desteğine ihtiyacınız varsa Mercurial'ı tercih edebilirsiniz. TortoiseHg (Windows explorer eklentisi) oldukça karmaşık bir araca kullanımı kolay bir grafik arayüzü sunmayı başarıyor. Burada durum olarak, bir Visual Studio eklentisine de sahip olacaksınız . Ancak, en son denediğimde, SVN arayüzü Windows'da iyi çalışmadı.

Komut satırı arayüzüne aldırmazsanız Git'i tavsiye ederim. Teknik nedenlerle değil, stratejik nedenlerle. Git'in benimsenme oranı çok daha yüksektir. Kaç tane ünlü açık kaynaklı projenin cvs / svn'den Mercurial'a ve kaçının Git'e geçtiğine bakın. Mercurial hosting'e kıyasla git desteği ile kaç tane kod / proje barındırma sağlayıcısı bulabileceğinizi görün.


Komut satırını kullanmaktan hoşlanmıyorsanız TortoiseGit de var. (Ancak msysgit'in kurulu olması gerekir.)
Ben James

2
Şirketimiz , Windows üzerindeki büyük desteği nedeniyle git'i seçti - Git Uzantıları'na bakın . Taraflıyım çünkü şimdi katkıda bulunuyorum, ama kullanmaya başladığımızda değildim.
Jacob Stanley

11

Mercurial'ın her şeyi okuduktan sonra (hala inanıyorum ki, tüm internet topluluğu fikrinden sonra), Git ve Mercurial ile çalışmaya başladığımda Git'in uyum sağlamam için nispeten daha basit olduğunu hissettim (başladım Komut satırından çalışırken, esas olarak git komutları bana göre uygun şekilde adlandırıldığından ve sayıları daha az olduğundan, Mercurial with TortoiseHg) . Mercurial, farklı bir iş yapan her komut için farklı adlandırmaya sahipken, Git komutları duruma göre çok amaçlı olabilir (örneğin,checkout). Git o zamanlar daha zorken, şimdi fark çok önemli değil. YMMV .. TortoiseHg gibi iyi bir GUI istemcisi ile, Mercurial ile çalışmak çok daha kolaydı ve biraz kafa karıştırıcı komutları hatırlamak zorunda değildim. Aynı eylem için her komutun nasıl değiştiğini ayrıntılı olarak anlatmıyorum , ancak iki kapsamlı liste var: 1 Mercurial'ın kendi sitesinden ve 2 wikiv'den .

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

Git, işlenen dosyaların her sürümünün kaydını dahili olarak kaydederken, Hg yalnızca daha az yer kaplayan değişiklik kümelerini kaydeder. Git, Hg'ye kıyasla geçmişi değiştirmeyi kolaylaştırır, ancak yine de bir nefret et ya da sev-sev özelliği. Eski için Hg'yi ve ikinci için Git'i seviyorum.

Hg'de özlediğim şey Git'in alt modül özelliğidir. Hg'nin alt depoları vardır, ancak bu tam olarak Git alt modülü değildir.

İkisinin etrafındaki ekosistem de kişinin seçimini etkileyebilir: Git daha popüler olmalı (ama bu önemsiz), GitHub , Mercurial'da BitBucket , Mercurial, TortoiseHg'ye sahip.

Her birinin avantajları ve dezavantajları vardır, her ikisiyle de kaybetmezsiniz.


8

Check out Scott Chacon adlı kullanıcının yayınını bir süre arkasından.

Bence git "daha karmaşık" bir üne sahip olsa da, benim deneyimime göre olması gerekenden daha karmaşık değil. IMO, git modelidir yolu (etiketleri sıfır veya daha fazla ana kaydedilmesini için kaydedilmesini (ve işaretçiler içerir) ihtiva ağaçlar bitmiş ... lekeler ve diğer ağaçlar içerir) anlamak daha kolay.

Git, mercurial'dan daha kafa karıştırıcı değil, sadece benim deneyimim değil. Bu konuda yine Scott Chacon'un bu blog yazısını okumanızı tavsiye ederim .


1
Mercurial model aslında neredeyse aynıdır: changelog, dosya revizyonları / blob ... Disk üzerindeki formatı karşılaştırıyorsanız, muhtemelen hg'den basit revlog formatından daha açıklamak için daha zor olan packs dosyasını hesaba katmadınız.
tonfa

Bu basitleştirilmiş model, hg'de pratikte oldukça daha karmaşık olan etiketlemeyi yok sayar (gerçi, varsayılan olarak bir etiket nesnesi oluşturmadığı için git etiketinin biraz kafa karıştırıcı olduğunu iddia ediyorum). Disk üzerinde format, çok sayıda dosya adı olan her iki proje için özellikle pahalıydı.
Dustin

1
Modelin etiketlemeyi görmezden geldiğini sanmıyorum: Mercurial'ta etiketleme önemsiz - bildiğiniz gibi, sadece SHA-1 karmalarına ad veren bir dosya. Etiketlerin sistemde nasıl aktığına dair tahmin yoktur: itme ve çekme ile birlikte hareket ederler. Bir etiket çakışması varsa, o zaman bunu çözmek de önemsizdir: başka bir çatışma gibi çözersiniz. Sonuçta, bu sadece bir metin dosyasında bir satır. Bence bu modelin sadeliği çok güzel bir özellik.
Martin Geisler

Dustin: Evet, kullanıcılar genellikle 1.0 sürümünü incelediğinizde 1.0 etiketini görememenizle karıştırılıyor .hgtags. Ancak, içeriye bakmanıza gerek yoktur .hgtagsve hg tagsyine de tüm etiketleri listelediğini görürsünüz . Ayrıca, bu davranış, etiketleri sürüm kontrollü bir dosyada saklamanın basit bir sonucudur - yine modelin kavranması kolaydır ve çok öngörülebilir .
Martin Geisler

1
Martin Geisler Mercurial'daki etiketler için kuralların, taşıma için sürüm kontrollü dosya kullandığından, etiketlerin sürümlendirilmemiş hale getirilmesi için özel kurallar üzerinde katman kullanması nedeniyle gerekli olduğunu iddia ediyorum.
Jakub Narębski

5

Git'i şu anki işimde bir yıldan biraz fazla kullandım ve ondan önce önceki işimde Mercurial'ı bir yıldan biraz fazla kullandım. Bir kullanıcının bakış açısından bir değerlendirme yapacağım.

İlk olarak, her ikisi de dağıtılmış sürüm kontrol sistemleridir. Dağıtılmış sürüm kontrol sistemleri, geleneksel sürüm kontrol sistemlerinden zihniyette bir değişiklik yapılmasını gerektirir, ancak bunları anladıktan sonra aslında çok daha iyi çalışır. Bu nedenle, hem Git hem de Mercurial'ı Subversion, Perforce, vs.'den çok daha üstün görüyorum. Dağıtılmış sürüm kontrol sistemleri ile geleneksel sürüm kontrol sistemleri arasındaki fark Git ve Mercurial arasındaki farktan çok daha büyük.

Bununla birlikte, Git ve Mercurial arasında her birini kendi kullanım alt kümelerine daha uygun hale getiren önemli farklılıklar da vardır.

Mercurial'ı öğrenmek daha kolaydır. Mercurial'ı kullandıktan birkaç hafta sonra nadiren belgelere veya notlara başvurmak zorunda olduğum noktaya geldim; Notlarımı bir yıl kullandıktan sonra bile Git'le düzenli olarak göndermem gerekiyor. Git çok daha karmaşıktır.

Bunun nedeni kısmen Mercurial'ın sade bir temizleyici olmasıdır. Mercurial'da nadiren manuel olarak dallanmak zorundasınız; Mercurial, ihtiyacınız olduğunda ve ihtiyaç duyduğunuzda sizin için otomatik olarak anonim bir şube oluşturur. Mercurial isimlendirmesi daha sezgiseldir; Git ile yaptığınız gibi "getirme" ve "çekme" arasındaki fark konusunda endişelenmenize gerek yoktur. Mercurial biraz daha az buggy. Projeleri hem Git hem de Mercurial ile platformlar arasında iterken sorunlara neden olan dosya adı büyük / küçük harf duyarlılığı sorunları vardır; Bu, bir süre önce Mercurial'da düzeltildi, en son Git'i kontrol etmediler. Mercurial'a dosya adları hakkında bilgi verebilirsiniz; Git ile yeniden adlandırmayı otomatik olarak algılamazsa - deneyimimde çok isabetli veya kaçırılmış bir teklif - yeniden adlandırma hiç izlenemez.

Ancak Git'in ek komplikasyonunun diğer nedeni, ek özellikleri ve gücü desteklemek için bunun çoğuna ihtiyaç duyulmasıdır. Evet, Git'te dallanmayı ele almak daha karmaşıktır - ancak öte yandan, bir kez dalınız olduğunda, bu dallarla Mercurial'ta neredeyse imkansız olan şeyleri yapmak çok zor değildir. Dallara yeniden bağlanmak şu şeylerden biridir: dalınızı, dallandığınızda gövdenin durumu yerine, şimdi gövdenin durumu olacak şekilde taşıyabilirsiniz; aynı kod tabanında çalışan birçok kişi olduğunda sürüm geçmişini büyük ölçüde basitleştirir, çünkü gövdeye yapılan itmelerin her birinin iç içe değil sıralı görünmesi sağlanabilir. Benzer şekilde, şubenizdeki birden fazla taahhüdü tek bir taahhütte daraltmak çok daha kolaydır,

Sonuç olarak, Mercurial ve Git arasındaki seçimin, sürüm kontrol projelerinizin aynı anda çalışan kişi sayısı açısından ölçülen büyüklüğüne bağlı olması gerektiğini düşünüyorum. Örneğin, tek bir monolitik web uygulaması üzerinde çalışan bir düzine veya daha fazla grubunuz varsa, Git'in daha güçlü şube yönetimi araçları onu projeniz için çok daha uygun hale getirecektir. Öte yandan, ekibiniz heterojen dağıtılmış bir sistem geliştiriyorsa, yalnızca bir veya iki geliştirici aynı anda herhangi bir bileşen üzerinde çalışıyorsa, bileşen projelerinin her biri için bir Mercurial deposu kullanmak, geliştirmenin daha az ile daha sorunsuz ilerlemesine izin verecektir. depo yönetim yükü.

Alt satır: Tek bir büyük uygulama geliştiren büyük bir ekibiniz varsa Git'i kullanın; bireysel uygulamalarınız küçükse, bu tür uygulamaların boyutu yerine sayıdan herhangi bir ölçek geliyorsa Mercurial kullanın.


4

DVCS'lerle tamamen ilgisi olmayan bir fark:

Git, C geliştiricileri arasında çok popüler görünüyor. Git, Linux Çekirdeği için fiili havuzdur ve C geliştiricileri arasında bu kadar popüler olmasının nedeni bu olabilir. Bu özellikle sadece Linux / Unix dünyasında çalışma lüksüne sahip olanlar için geçerlidir.

Java geliştiricileri Git yerine Mercurial'ı tercih ediyor gibi görünüyor. Bunun iki nedeni olabilir: Birincisi, JDK'nın kendisi de dahil olmak üzere Mercurial'da çok sayıda büyük Java projesinin barındırılmasıdır. Bir diğeri, Mercurial'ın yapısının ve temiz dokümantasyonunun Java kampından gelen insanlara hitap etmesidir, ancak bu tür insanlar Git'i dokümantasyonda tutarsız wrt komut adlandırma ve eksik bulmaktadır. Bunun gerçek olduğunu söylemiyorum, insanların normal yaşam alanlarından bir şeye alıştıklarını ve daha sonra DVCS'yi seçme eğiliminde olduklarını söylüyorum.

Python geliştiricileri neredeyse tamamen Mercurial'ı tercih ediyor, sanırım. Mercurial'ın Python'a dayandırılması dışında bunun akılcı bir nedeni yoktur. (Mercurial'ı da kullanıyorum ve insanların neden DVCS'nin uygulama dili hakkında bir karışıklık yarattığını gerçekten anlamıyorum. Python'un bir kelimesini anlamıyorum ve bunun bir yerde listelendiği için değilse Python'a dayanıyor o zaman bilemezdim).

Bir DVCS'nin bir dile diğerinden daha iyi uyduğunu söyleyebileceğinizi sanmıyorum, bu yüzden bundan seçim yapmamalısınız. Ancak gerçekte insanlar (kısmen) hangi DVCS'lere en çok maruz kaldıklarını seçerler.

(hayır, yukarıdaki iddialarımı destekleyecek kullanım istatistiklerim yok .. hepsi kendi öznelliğime dayanıyor)

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.