Untuk sementara sekarang saya telah menggunakan subversi untuk proyek pribadi saya.
Semakin banyak saya terus mendengar hal-hal hebat tentang Git dan Mercurial, dan DVCS secara umum.
Saya ingin memberikan seluruh pusaran hal-hal DVCS, tapi saya tidak terlalu akrab dengan pilihan baik.
Apa perbedaan antara Mercurial dan Git?
Catatan: Saya tidak berusaha mencari tahu mana yang "terbaik" atau bahkan mana yang harus saya mulai. Saya terutama mencari bidang-bidang utama di mana mereka serupa, dan di mana mereka berbeda, karena saya tertarik untuk mengetahui perbedaannya dalam hal implementasi dan filosofi.
Jawaban:
Penafian: Saya menggunakan Git, ikuti pengembangan Git di milis git, dan bahkan berkontribusi sedikit pada Git (terutama gitweb). Saya tahu Mercurial dari dokumentasi dan beberapa dari diskusi di kanal IRC #revctrl di FreeNode.
Terima kasih kepada semua orang di saluran IRC #mercurial yang memberikan bantuan tentang Mercurial untuk penulisan ini
Ringkasan
Di sini akan menyenangkan untuk memiliki beberapa sintaks untuk tabel, sesuatu seperti di PHPMarkdown / MultiMarkdown / Maruku ekstensi Markdown
.hgtags
file berversi dengan aturan khusus untuk tag per-repositori, dan juga mendukung tag lokal di.hg/localtags
; di Git tag adalah referensi yang berada direfs/tags/
namespace, dan secara default diikutkan secara otomatis pada pengambilan dan memerlukan dorongan eksplisit.Ada beberapa hal yang berbeda Mercurial dari Git, tetapi ada hal-hal lain yang membuatnya serupa. Kedua proyek saling meminjam ide. Misalnya
hg bisect
perintah dalam Mercurial (sebelumnya ekstensi dua bagian ) diilhami olehgit bisect
perintah di Git, sementara idegit bundle
diilhami olehhg bundle
.Struktur repositori, menyimpan revisi
Di Git ada empat jenis objek dalam database objeknya: objek gumpalan yang berisi konten file, objek hierarki pohon yang menyimpan struktur direktori, termasuk nama file dan bagian yang relevan dari izin file (izin yang dapat dieksekusi untuk file, menjadi tautan simbolik) , komit objek yang berisi informasi kepengarangan, penunjuk ke snapshot keadaan repositori pada revisi yang diwakili oleh komit (melalui objek pohon direktori proyek teratas) dan referensi ke nol atau lebih komit induk, dan menandai objek yang mereferensikan objek lain dan dapat ditandatangani menggunakan PGP / GPG.
Git menggunakan dua cara menyimpan objek: format longgar , di mana setiap objek disimpan dalam file terpisah (file-file itu ditulis sekali, dan tidak pernah dimodifikasi), dan dikemas format yang mana banyak objek disimpan delta-dikompresi dalam satu file. Atomicity operasi disediakan oleh fakta, bahwa referensi ke objek baru ditulis (secara atomis, menggunakan trik buat + ganti nama) setelah menulis objek.
Repositori Git memerlukan pemeliharaan berkala menggunakan
git gc
(untuk mengurangi ruang disk dan meningkatkan kinerja), meskipun saat ini Git melakukannya secara otomatis. (Metode ini memberikan kompresi repositori yang lebih baik.)Mercurial (sejauh yang saya mengerti) menyimpan sejarah file dalam filelog (bersama-sama, saya pikir, dengan metadata tambahan seperti pelacakan nama, dan beberapa informasi pembantu); menggunakan struktur datar yang disebut manifes untuk menyimpan struktur direktori, dan struktur yang disebut changelog yang menyimpan informasi tentang perubahan (revisi), termasuk pesan komit dan nol, satu atau dua orang tua.
Mercurial menggunakan jurnal transaksi untuk memberikan atomicity operasi, dan bergantung pada pemotongan file untuk pembersihan setelah operasi gagal atau terputus. Revlog hanya untuk penambahan.
Melihat struktur repositori di Git versus di Mercurial, orang dapat melihat bahwa Git lebih mirip database objek (atau sistem file yang ditujukan pada konten), dan Mercurial lebih seperti database relasional bidang tetap tradisional.
Perbedaan:
Dalam Git objek pohon membentuk struktur hierarkis ; dalam file manifes Mercurial adalah struktur datar . Dalam objek Git blob, simpan satu versi isi file; di Mercurial filelog menyimpan seluruh riwayat satu file (jika kita tidak memperhitungkan segala komplikasi dengan penggantian nama di sini). Ini berarti bahwa ada area operasi yang berbeda di mana Git akan lebih cepat daripada Mercurial, semua hal lain dianggap sama (seperti penggabungan, atau menunjukkan sejarah proyek), dan area di mana Mercurial akan lebih cepat daripada Git (seperti menerapkan tambalan, atau menunjukkan riwayat satu file).Masalah ini mungkin tidak penting bagi pengguna akhir.
Karena struktur catatan tetap dari struktur changelog Mercurial , komit di Mercurial hanya dapat memiliki hingga dua orang tua ; komit di Git dapat memiliki lebih dari dua orang tua (disebut "gurita bergabung"). Meskipun Anda (secara teori) dapat mengganti penggabungan gurita dengan serangkaian penggabungan dua induk, ini dapat menyebabkan komplikasi saat mengkonversi antara repositori Mercurial dan Git.
Sejauh yang saya tahu Mercurial tidak memiliki setara dengan tag beranotasi (objek tag) dari Git. Kasus khusus dari tag beranotasi adalah tag yang ditandatangani (dengan tanda tangan PGP / GPG); setara dalam Mercurial dapat dilakukan menggunakan GpgExtension , yang ekstensi sedang didistribusikan bersama dengan Mercurial. Anda tidak dapat menandai objek non-komit di Mercurial seperti yang Anda bisa di Git, tapi itu tidak terlalu penting, saya pikir (beberapa repositori git menggunakan gumpalan yang ditandai untuk mendistribusikan kunci PGP publik yang digunakan untuk memverifikasi tag yang ditandatangani).
Referensi: cabang dan tag
Dalam referensi Git (cabang, cabang dan tag pelacak jarak jauh) berada di luar DAG dari commit (sebagaimana mestinya). Referensi dalam
refs/heads/
namespace ( cabang lokal ) menunjuk ke commit, dan biasanya diperbarui oleh "git commit"; mereka menunjuk ke ujung (kepala) cabang, itu sebabnya nama seperti itu. Referensi dalamrefs/remotes/<remotename>/
namespace ( cabang pelacakan jarak jauh ) menunjuk untuk melakukan, mengikuti cabang di repositori jarak jauh<remotename>
, dan diperbarui dengan "git fetch" atau yang setara. Referensi dalamrefs/tags/
namespace ( tag ) menunjuk biasanya untuk melakukan (tag ringan) atau objek tag (tag beranotasi dan bertanda tangan), dan tidak dimaksudkan untuk berubah.Tag
Di Mercurial, Anda dapat memberikan nama tetap untuk direvisi menggunakan tag ; tag disimpan mirip dengan pola abaikan. Ini berarti bahwa tag yang terlihat secara global disimpan dalam
.hgtags
file yang dikendalikan revisi dalam repositori Anda. Itu memiliki dua konsekuensi: pertama, Mercurial harus menggunakan aturan khusus untuk file ini untuk mendapatkan daftar semua tag saat ini dan untuk memperbarui file tersebut (misalnya, ia membaca revisi terbaru dari file tersebut, saat ini tidak memeriksa versi); kedua, Anda harus melakukan perubahan pada file ini agar tag baru terlihat oleh pengguna lain / repositori lainnya (sejauh yang saya mengerti).Mercurial juga mendukung tag lokal , disimpan di
hg/localtags
, yang tidak terlihat oleh orang lain (dan tentu saja tidak dapat ditransfer)Dalam Git tag diperbaiki (konstan) bernama referensi ke objek lain (biasanya tag objek, yang pada gilirannya mengarah ke komit) disimpan dalam
refs/tags/
namespace. Secara default ketika mengambil atau mendorong satu set revisi, git secara otomatis mengambil atau mendorong tag yang mengarah ke revisi yang diambil atau didorong. Namun demikian, Anda dapat mengontrol sampai batas mana tag diambil atau didorong.Git memperlakukan tag ringan (menunjuk langsung ke komit) dan tag beranotasi (menunjuk ke objek tag, yang berisi pesan tag yang secara opsional menyertakan tanda tangan PGP, yang pada gilirannya mengarah ke komit) sedikit berbeda, misalnya secara default hanya menganggap tag beranotasi ketika menggambarkan berkomitmen menggunakan "git mendeskripsikan".
Git tidak memiliki tag lokal yang setara dengan Mercurial. Namun demikian git best practices merekomendasikan untuk menyiapkan repositori telanjang publik yang terpisah, tempat Anda mendorong perubahan siap, dan dari mana orang lain mengkloning dan mengambil. Ini berarti bahwa tag (dan cabang) yang tidak Anda push, bersifat pribadi untuk repositori Anda. Di sisi lain Anda juga dapat menggunakan namespace selain
heads
,remotes
atautags
, misalnyalocal-tags
untuk tag lokal.Pendapat pribadi: Menurut saya, tag harus berada di luar grafik revisi, karena merupakan eksternal dari itu (mereka adalah penunjuk ke grafik revisi). Tag harus bukan versi, tetapi dapat ditransfer. Pilihan Mercurial untuk menggunakan mekanisme yang mirip dengan yang digunakan untuk mengabaikan file, berarti bahwa ia harus memperlakukan
.hgtags
secara khusus (file in-tree dapat ditransfer, tetapi biasanya ini berversi), atau memiliki tag yang hanya bersifat lokal (.hg/localtags
bukan versi, tetapi tidak bisa dipindahtangankan).Ranting
Di Git, cabang lokal (ujung cabang, atau kepala cabang) adalah referensi yang dinamai komit, tempat seseorang dapat menumbuhkan komit baru. Cabang juga dapat berarti garis pengembangan aktif, yaitu semua komit dapat dicapai dari ujung cabang. Cabang lokal berada di
refs/heads/
namespace, jadi mis. Nama cabang 'master' yang sepenuhnya memenuhi syarat adalah 'ref / head / master'.Cabang saat ini di Git (artinya cabang yang dicek, dan cabang tempat komit baru akan dituju) adalah cabang yang direferensikan oleh referensi HEAD. Seseorang dapat memiliki KEPALA menunjuk langsung ke sebuah komit, daripada menjadi referensi simbolis; situasi berada di cabang tanpa nama anonim disebut HEAD terlepas ("cabang git" menunjukkan bahwa Anda menggunakan '(tanpa cabang)').
Di Mercurial ada cabang anonim (kepala cabang), dan orang dapat menggunakan bookmark (melalui ekstensi bookmark ). Cabang - cabang bookmark semacam itu murni lokal, dan nama-nama itu (hingga versi 1.6) tidak dapat ditransfer menggunakan Mercurial. Anda dapat menggunakan rsync atau scp untuk menyalin
.hg/bookmarks
file ke repositori jarak jauh. Anda juga dapat menggunakanhg id -r <bookmark> <url>
untuk mendapatkan id revisi dari ujung bookmark saat ini.Karena 1.6 bookmark dapat didorong / ditarik. The BookmarksExtension halaman memiliki bagian tentang Kerja Dengan Remote Repositori . Ada perbedaan bahwa dalam nama bookmark Mercurial bersifat global , sedangkan definisi 'jarak jauh' di Git menjelaskan juga pemetaan nama cabang dari nama-nama dalam repositori jarak jauh ke nama cabang pelacakan jarak jauh lokal; misalnya
refs/heads/*:refs/remotes/origin/*
pemetaan berarti bahwa seseorang dapat menemukan keadaan cabang 'master' ('ref / head / master') di repositori jauh di cabang pelacakan jarak jauh 'asal / master' ('ref / remote / asal / master /').Mercurial juga disebut cabang bernama , di mana nama cabang tertanam dalam komit (dalam changeset). Nama tersebut bersifat global (ditransfer saat mengambil). Nama-nama cabang dicatat secara permanen sebagai bagian dari metadata changeset. Dengan Mercurial modern Anda dapat menutup "cabang bernama" dan berhenti merekam nama cabang. Dalam mekanisme ini, tip cabang dihitung dengan cepat.
"Cabang bernama" Mercurial harusnya menurut saya disebut label komit saja, karena memang itulah namanya. Ada situasi di mana "cabang bernama" dapat memiliki banyak kiat (banyak komitmen tanpa anak), dan juga dapat terdiri dari beberapa bagian grafik revisi yang terpisah.
Tidak ada yang setara dengan "cabang tertanam" Mercurial di Git; selain itu filosofi Git adalah bahwa sementara seseorang dapat mengatakan bahwa cabang mencakup beberapa komit, itu tidak berarti bahwa komit adalah milik beberapa cabang.
Perhatikan bahwa dokumentasi Mercurial masih mengusulkan untuk menggunakan klon terpisah (repositori terpisah) setidaknya untuk cabang yang berumur panjang (cabang tunggal per alur kerja repositori), alias bercabang dengan kloning .
Cabang dalam mendorong
Mercurial secara default mendorong semua kepala . Jika Anda ingin mendorong satu cabang ( kepala tunggal ), Anda harus menentukan tip revisi cabang yang ingin Anda dorong. Anda dapat menentukan tip cabang dengan nomor revisi (lokal ke repositori), dengan pengidentifikasi revisi, dengan nama bookmark (lokal ke repositori, tidak dapat ditransfer), atau dengan nama cabang tertanam (bernama cabang).
Sejauh yang saya pahami, jika Anda mendorong serangkaian revisi yang berisi komit yang ditandai berada di beberapa "cabang bernama" dalam bahasa Mercurial, Anda akan memiliki "cabang bernama" ini di repositori yang Anda dorong. Ini berarti bahwa nama-nama cabang tertanam tersebut ("cabang bernama") bersifat global (sehubungan dengan klon repositori / proyek yang diberikan).
Secara default (tergantung pada
push.default
variabel konfigurasi) "git push" atau "git push < remote >" Git akan mendorong cabang-cabang yang cocok , yaitu hanya cabang-cabang lokal yang memiliki padanannya yang sudah ada dalam repositori jarak jauh yang Anda dorong. Anda dapat menggunakan--all
opsi untuk git-push ("git push --all") untuk mendorong semua cabang , Anda dapat menggunakan "git push < remote > < branch >" untuk mendorong cabang tunggal yang diberikan , dan Anda dapat menggunakan "git push < remote > KEPALA "untuk mendorong cabang saat ini .Semua hal di atas mengasumsikan bahwa Git tidak mengkonfigurasi cabang mana yang harus didorong melalui
remote.<remotename>.push
variabel konfigurasi.Cabang dalam mengambil
Catatan: di sini saya menggunakan terminologi Git di mana "fetch" berarti mengunduh perubahan dari repositori jarak jauh tanpa mengintegrasikan perubahan itu dengan pekerjaan lokal. Inilah yang dilakukan "
git fetch
" dan "hg pull
".Jika saya memahaminya dengan benar, secara default Mercurial mengambil semua kepala dari repositori jarak jauh, tetapi Anda dapat menentukan cabang yang akan diambil melalui "
hg pull --rev <rev> <url>
" atau "hg pull <url>#<rev>
" untuk mendapatkan cabang tunggal . Anda dapat menentukan <rev> menggunakan pengidentifikasi revisi, nama "bernama cabang" (cabang tertanam di changelog), atau nama bookmark. Namun nama bookmark (setidaknya saat ini) tidak dapat ditransfer. Semua revisi "cabang bernama" yang Anda miliki menjadi bagian untuk ditransfer. "hg pull" menyimpan ujung cabang yang diambilnya sebagai kepala tanpa nama, tanpa nama.Di Git secara default (untuk remote 'origin' dibuat oleh "git clone", dan untuk remote yang dibuat menggunakan "git remote add") "
git fetch
" (atau "git fetch <remote>
") mendapatkan semua cabang dari repositori jarak jauh (darirefs/heads/
namespace), dan menyimpannya direfs/remotes/
namespace. Ini berarti misalnya cabang yang bernama 'master' (nama lengkap: 'ref / head / master') di 'asal' jauh akan disimpan (disimpan) sebagai cabang pelacakan jarak jauh 'asal / master' (nama lengkap: 'ref / remote / asal / master ').Anda dapat mengambil cabang tunggal di Git dengan menggunakan
git fetch <remote> <branch>
- Git akan menyimpan cabang yang diminta di FETCH_HEAD, yang mirip dengan kepala Mercurial tanpa nama.Itu hanyalah contoh kasus default sintaks Git refspec yang kuat : dengan refspec Anda dapat menentukan dan / atau mengkonfigurasi cabang mana yang ingin diambil, dan tempat menyimpannya. Misalnya kasus "ambil semua cabang" default diwakili oleh '+ ref / kepala / *: refs / remote / asal / *' wildcard refspec, dan "ambil cabang tunggal" adalah singkatan untuk 'ref / kepala / <branch>:' . Refspec digunakan untuk memetakan nama cabang (ref) dalam repositori jarak jauh ke nama referensi lokal. Tetapi Anda tidak perlu tahu (banyak) tentang refspec untuk dapat bekerja secara efektif dengan Git (terutama berkat perintah "git remote").
Pendapat pribadi: Saya pribadi berpikir bahwa "cabang bernama" (dengan nama cabang tertanam dalam metadata changeset) di Mercurial adalah desain yang salah arah dengan namespace globalnya, terutama untuk sistem kontrol versi terdistribusi . Sebagai contoh, mari kita ambil contoh di mana Alice dan Bob memiliki "nama cabang" bernama 'for-joe' di repositori mereka, cabang-cabang yang tidak memiliki kesamaan. Namun dalam repositori Joe, kedua cabang itu akan diperlakukan secara salah sebagai satu cabang. Jadi, entah bagaimana, Anda membuat konvensi yang melindungi terhadap bentrokan nama cabang. Ini bukan masalah dengan Git, di mana dalam repositori Joe 'untuk-joe' cabang dari Alice akan menjadi 'alice / untuk-joe', dan dari Bob itu akan menjadi 'bob / untuk-joe'.
"Cabang penunjuk" Mercurial saat ini kekurangan mekanisme distribusi inti.
Perbedaan:
Area ini adalah salah satu perbedaan utama antara Mercurial dan Git, seperti yang dikatakan james woodyatt dan Steve Losh dalam jawaban mereka. Mercurial, secara default, menggunakan codelines ringan anonim, yang dalam terminologinya disebut "kepala". Git menggunakan cabang bernama ringan, dengan pemetaan injeksi untuk memetakan nama-nama cabang dalam repositori jarak jauh ke nama-nama cabang pelacakan jarak jauh. Git "memaksa" Anda untuk memberi nama cabang (well, dengan pengecualian cabang tunggal yang tidak disebutkan namanya, situasi yang disebut HEAD terpisah), tapi saya pikir ini bekerja lebih baik dengan alur kerja cabang-berat seperti alur kerja cabang topik, yang berarti banyak cabang dalam paradigma repositori tunggal.
Penamaan revisi
Di Git ada banyak cara penamaan revisi (dijelaskan misalnya dalam manual git rev-parse ):
^
Parameter suffix to revisi berarti induk pertama dari objek komit,^n
berarti induk ke-n dari komit gabungan.~n
Parameter suffix to revisi berarti leluhur ke-11 dari komit dalam garis induk pertama lurus. Sufiks-sufiks itu dapat digabungkan, untuk membentuk specifier revisi mengikuti jalur dari referensi simbolis, misalnya 'pu ~ 3 ^ 2 ~ 3'Ada juga penentu revisi yang melibatkan reflog, tidak disebutkan di sini. Di Git setiap objek, baik itu komit, tag, pohon atau gumpalan memiliki pengidentifikasi SHA-1-nya; ada sintaks khusus seperti misalnya 'selanjutnya: Dokumentasi' atau 'berikutnya: README' untuk merujuk ke pohon (direktori) atau gumpalan (isi file) pada revisi yang ditentukan.
Mercurial juga memiliki banyak cara penamaan perubahan (dijelaskan misalnya dalam halaman hg ):
Perbedaan
Seperti yang Anda lihat membandingkan daftar di atas Mercurial menawarkan angka revisi, lokal ke repositori, sedangkan Git tidak. Di sisi lain Mercurial menawarkan offset relatif hanya dari 'tip' (cabang saat ini), yang bersifat lokal untuk repositori (setidaknya tanpa ParentrevspecExtension ), sementara Git memungkinkan untuk menentukan komit berikut dari tip apa pun.
Revisi terbaru bernama HEAD in Git, dan "tip" dalam Mercurial; tidak ada revisi nol di Git. Baik Mercurial dan Git dapat memiliki banyak root (dapat memiliki lebih dari satu komitmen tanpa orangtua; ini biasanya merupakan hasil dari bergabungnya proyek yang sebelumnya terpisah).
Lihat juga: Berbagai jenis artikel penentu revisi di Blog Elia (berita baru).
Pendapat pribadi: Saya pikir angka revisi terlalu dibesar-besarkan (setidaknya untuk pengembangan terdistribusi dan / atau sejarah nonlinear / bercabang). Pertama, untuk sistem kontrol versi terdistribusi, mereka harus bersifat lokal untuk repositori, atau mengharuskan memperlakukan beberapa repositori dengan cara khusus sebagai otoritas penomoran pusat. Kedua, proyek-proyek yang lebih besar, dengan sejarah yang lebih panjang, dapat memiliki sejumlah revisi dalam rentang 5 digit sehingga mereka hanya menawarkan sedikit keuntungan dibandingkan dengan disingkat menjadi 6-7 pengenal revisi karakter, dan menyiratkan pemesanan ketat sementara revisi hanya dipesan sebagian (maksud saya di sini adalah bahwa revisi n dan n +1 tidak perlu menjadi orang tua dan anak).
Rentang revisi
Dalam rentang revisi Git bersifat topologis .
A..B
Sintaks yang umum dilihat , yang untuk sejarah linier berarti rentang revisi mulai dari A (tetapi tidak termasuk A), dan berakhir di B (yaitu rentang terbuka dari bawah ), adalah singkatan ("gula sintaksis") untuk^A B
, yang untuk perintah traverse sejarah berarti semua berkomitmen dapat dijangkau dari B, tidak termasuk yang dapat dicapai dari A. Ini berarti bahwa perilakuA..B
rentang sepenuhnya dapat diprediksi (dan cukup berguna) bahkan jika A bukan merupakan leluhur B:A..B
berarti kemudian rentang revisi dari leluhur bersama A dan B (basis gabungan ) untuk revisi B.Dalam rentang revisi Mercurial didasarkan pada kisaran angka revisi . Rentang ditentukan menggunakan
A:B
sintaks, dan bertentangan dengan rentang Git bertindak sebagai interval tertutup . Juga rentang B: A adalah kisaran A: B dalam urutan terbalik, yang tidak terjadi pada Git (tetapi lihat catatan di bawah ini tentangA...B
sintaks). Tetapi kesederhanaan seperti itu datang dengan harga: rentang revisi A: B masuk akal hanya jika A adalah leluhur B atau sebaliknya, yaitu dengan sejarah linier; jika tidak (saya rasa itu) kisaran tidak dapat diprediksi, dan hasilnya adalah lokal untuk repositori (karena angka revisi adalah lokal ke repositori).Ini diperbaiki dengan Mercurial 1.6, yang memiliki rentang revisi topologi baru , di mana 'A..B' (atau 'A :: B') dipahami sebagai sekumpulan perubahan yang keduanya merupakan keturunan X dan leluhur Y. Ini adalah , Saya kira, setara dengan '--ancestry-path A..B' di Git.
Git juga memiliki notasi
A...B
untuk perbedaan revisi simetris; itu berartiA B --not $(git merge-base A B)
, yang berarti semua komit dapat dicapai baik dari A atau B, tetapi tidak termasuk semua komit yang dapat dicapai dari keduanya (dapat dicapai dari leluhur bersama).Ganti nama
Mercurial menggunakan pelacakan nama untuk berurusan dengan nama file. Ini berarti bahwa informasi tentang fakta bahwa suatu file diganti namanya disimpan pada waktu yang ditentukan; di Mercurial, informasi ini disimpan dalam bentuk "enhanced diff" dalam metadata filelog (file revlog). Konsekuensi dari ini adalah bahwa Anda harus menggunakan
hg rename
/hg mv
... atau Anda harus ingat untuk menjalankanhg addremove
untuk melakukan deteksi nama berdasarkan kesamaan.Git unik di antara sistem kontrol versi karena menggunakan deteksi nama untuk menangani nama file. Ini berarti fakta bahwa file diubah namanya terdeteksi pada saat diperlukan: ketika melakukan penggabungan, atau ketika menampilkan diff (jika diminta / dikonfigurasi). Ini memiliki keuntungan bahwa mengubah nama algoritma deteksi dapat ditingkatkan, dan tidak dibekukan pada saat melakukan.
Baik Git dan Mercurial memerlukan
--follow
opsi menggunakan untuk mengikuti penggantian nama saat menampilkan riwayat satu file. Keduanya dapat mengikuti penggantian nama saat menampilkan riwayat baris-bijaksana dari file digit blame
/hg annotate
.Di Git,
git blame
perintah ini dapat mengikuti pergerakan kode, juga memindahkan (atau menyalin) kode dari satu file ke yang lain, bahkan jika perpindahan kode bukan bagian dari penggantian nama file yang sehat. Sejauh yang saya tahu fitur ini unik untuk Git (pada saat penulisan, Oktober 2009).Protokol jaringan
Baik Mercurial dan Git memiliki dukungan untuk mengambil dari dan mendorong ke repositori pada sistem file yang sama, di mana URL repositori hanyalah jalur sistem file ke repositori. Keduanya juga memiliki dukungan untuk mengambil dari file bundel .
Dukungan Mercurial mengambil dan mendorong melalui SSH dan melalui protokol HTTP. Untuk SSH kita membutuhkan akun shell yang dapat diakses di mesin tujuan dan salinan hg diinstal / tersedia. Untuk akses HTTP,
hg-serve
atau menjalankan skrip Mercurial CGI diperlukan, dan Mercurial perlu diinstal pada mesin server.Git mendukung dua jenis protokol yang digunakan untuk mengakses repositori jarak jauh:
git-daemon
), mengharuskan git diinstal pada server. Pertukaran dalam protokol-protokol tersebut terdiri dari klien dan server yang bernegosiasi tentang objek apa yang mereka miliki bersama, dan kemudian menghasilkan dan mengirim paketfile. Modern Git termasuk dukungan untuk protokol HTTP "pintar".git update-server-info
(biasanya dijalankan dari hook ). Pertukaran terdiri dari klien yang menjalankan rantai komit dan mengunduh objek dan paket yang longgar sesuai kebutuhan. Kelemahannya adalah ia mengunduh lebih dari yang dibutuhkan secara ketat (mis. Dalam kasus sudut ketika hanya ada satu paket file yang akan diunduh secara keseluruhan bahkan ketika mengambil hanya beberapa revisi), dan itu dapat membutuhkan banyak koneksi untuk menyelesaikannya.Extending: scriptability vs extensions (plugins)
Mercurial diimplementasikan dalam Python , dengan beberapa kode inti ditulis dalam C untuk kinerja. Ini menyediakan API untuk menulis ekstensi (plugin) sebagai cara menambahkan fitur tambahan. Beberapa fungsi, seperti "cabang bookmark" atau menandatangani revisi, disediakan dalam ekstensi yang didistribusikan bersama Mercurial dan mengharuskan untuk mengaktifkannya.
Git diimplementasikan dalam skrip C , Perl dan shell . Git menyediakan banyak perintah level rendah ( pipa ledeng ) yang cocok untuk digunakan dalam skrip. Cara biasa untuk memperkenalkan fitur baru adalah dengan menuliskannya sebagai Perl atau skrip shell, dan ketika antarmuka pengguna menstabilkan penulisan ulang dalam C untuk kinerja, portabilitas, dan dalam kasus skrip shell menghindari kasus sudut (prosedur ini disebut builtinification ).
Git mengandalkan dan dibangun di sekitar format [repositori] dan protokol [jaringan]. Alih-alih binding bahasa ada (sebagian atau lengkap) implementasi ulang Git dalam bahasa lain (beberapa di antaranya adalah implementasi ulang sebagian, dan sebagian pembungkus di sekitar perintah git): JGit (Jawa, digunakan oleh EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).
TL; DR
sumber
Saya pikir Anda bisa merasakan apa sistem yang serupa atau berbeda dengan menangkap kedua video:
Linus Torvalds di Git ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Bryan O'Sullivan di Mercurial ( http://www.youtube.com/watch?v=JExtkqzEoHY )
Keduanya sangat mirip dalam desain tetapi sangat berbeda dalam implementasinya.
Saya menggunakan Mercurial. Sejauh yang saya mengerti Git, satu hal utama git berbeda adalah bahwa ia melacak isi file, bukan file itu sendiri. Linus mengatakan bahwa jika Anda memindahkan suatu fungsi dari satu file ke file lainnya, Git akan memberi tahu Anda sejarah fungsi tunggal tersebut di seluruh langkah.
Mereka juga mengatakan bahwa git lebih lambat daripada HTTP tetapi memiliki protokol jaringan dan server sendiri.
Git bekerja lebih baik sebagai klien tebal SVN daripada Mercurial. Anda dapat menarik dan mendorong server SVN. Fungsi ini masih dalam pengembangan di Mercurial
Baik Mercurial dan Git memiliki solusi hosting web yang sangat bagus (BitBucket dan GitHub), tetapi Google Code hanya mendukung Mercurial. Ngomong-ngomong, mereka memiliki perbandingan Mercurial dan Git yang sangat rinci yang mereka lakukan untuk memutuskan mana yang akan didukung ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Ini memiliki banyak info bagus.
sumber
Saya menulis entri blog tentang model percabangan Mercurial beberapa waktu lalu, dan menyertakan perbandingan dengan model percabangan git. Mungkin Anda akan menganggapnya menarik: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/
sumber
Saya menggunakan keduanya secara teratur. Perbedaan fungsional utama adalah dalam cara Git dan Mercurial menamai cabang dalam repositori. Dengan Mercurial, nama cabang diklon dan ditarik bersama dengan perubahannya. Saat Anda menambahkan perubahan ke cabang baru di Mercurial dan mendorong ke repositori lain, nama cabang didorong secara bersamaan. Jadi, nama-nama cabang lebih atau kurang global di Mercurial, dan Anda harus menggunakan ekstensi Bookmark untuk memiliki nama ringan khusus lokal (jika Anda menginginkannya; Mercurial, secara default, menggunakan codeline ringan anonim, yang dalam terminologinya adalah disebut "kepala"). Di Git, nama-nama cabang dan pemetaan injeksi mereka ke cabang-cabang terpencil disimpan secara lokal dan Anda harus mengelolanya secara eksplisit, yang berarti mengetahui cara melakukannya.
Seperti yang akan dicatat orang lain di sini, ada banyak perbedaan kecil. Masalahnya dengan cabang adalah pembeda besar.
sumber
Lihatlah Git vs Mercurial: Silakan Bersantai posting blog oleh Patrick Thomson, di mana ia menulis:
Git adalah MacGyver , Mercurial adalah James Bond
Perhatikan bahwa posting blog ini adalah dari 7 Agustus 2008, dan kedua SCM meningkat banyak sejak itu.
sumber
Mercurial hampir sepenuhnya ditulis dalam python. Inti Git ditulis dalam C (dan harus lebih cepat, daripada Mercurial) dan alat yang ditulis dalam sh, perl, tcl dan menggunakan utilitas GNU standar. Oleh karena itu perlu membawa semua utils dan interpreter ini ke sistem yang tidak mengandungnya (misalnya Windows).
Keduanya mendukung bekerja dengan SVN, meskipun dukungan AFAIK svn rusak untuk git di Windows (mungkin saya hanya sial / lumpuh, siapa tahu). Ada juga ekstensi yang memungkinkan untuk beroperasi antara git dan Mercurial.
Mercurial memiliki integrasi Visual Studio yang bagus . Terakhir kali saya memeriksa, plugin untuk Git berfungsi tetapi sangat lambat.
Mereka set perintah dasar sangat mirip (init, clone, tambah, status, komit, dorong, tarik dll). Jadi, alur kerja dasarnya akan sama. Juga, ada klien seperti TortoiseSVN untuk keduanya.
Ekstensi untuk Mercurial dapat ditulis dengan python (tidak mengherankan!) Dan untuk git mereka dapat ditulis dalam bentuk yang dapat dieksekusi (biner yang dapat dieksekusi, skrip shell, dll.). Beberapa ekstensi sangat kuat, seperti
git bisect
.sumber
Jika Anda membutuhkan dukungan Windows yang baik, Anda mungkin lebih suka Mercurial. TortoiseHg (plugin Windows explorer) mengelola untuk menawarkan antarmuka grafis yang mudah digunakan ke alat yang agak rumit. Sebagai status di sini, Anda juga akan memiliki plugin Visual Studio . Namun, terakhir kali saya mencoba, antarmuka SVN tidak berfungsi dengan baik di Windows.
Jika Anda tidak keberatan dengan antarmuka baris perintah, saya akan merekomendasikan Git. Bukan karena alasan teknis tetapi karena alasan strategis. Tingkat adopsi git jauh lebih tinggi. Lihat saja berapa banyak proyek open source terkenal yang beralih dari cvs / svn ke Mercurial dan berapa banyak yang beralih ke Git. Lihat berapa banyak penyedia hosting kode / proyek yang dapat Anda temukan dengan dukungan git dibandingkan dengan hosting Mercurial.
sumber
Setelah membaca semua yang Mercurial lebih mudah (yang saya masih percaya, setelah semua komunitas internet berpendapat), ketika saya mulai bekerja dengan Git dan Mercurial saya merasa Git relatif lebih mudah bagi saya untuk beradaptasi (saya mulai dengan Mercurial dengan TortoiseHg) ketika bekerja dari baris perintah, terutama karena perintah git dinamai sesuai dengan saya dan jumlahnya lebih sedikit. Mercurial memiliki penamaan yang berbeda untuk setiap perintah yang melakukan pekerjaan yang berbeda, sedangkan perintah Git dapat multiguna sesuai dengan situasi (misalnya,
checkout
). Sementara Git lebih sulit saat itu, sekarang perbedaannya hampir tidak substansial. YMMV .. Dengan klien GUI yang baik seperti TortoiseHg, benar itu jauh lebih mudah untuk bekerja dengan Mercurial dan saya tidak harus mengingat perintah yang sedikit membingungkan. Saya tidak akan menjelaskan secara terperinci bagaimana setiap perintah untuk tindakan yang sama bervariasi, tetapi di sini ada dua daftar lengkap: 1 dari situs Mercurial sendiri danke-2 dari wikiv .Git menyimpan catatan setiap versi file yang dilakukan secara internal, sementara Hg menyimpan hanya perubahan yang dapat memiliki jejak yang lebih kecil. Git membuatnya lebih mudah untuk mengubah sejarah dibandingkan dengan Hg, tetapi sekali lagi itu fitur benci-itu-atau-cinta-itu. Saya suka Hg untuk mantan dan Git untuk yang terakhir.
Apa yang saya lewatkan di Hg adalah fitur submodule dari Git. Hg memiliki subrepo tapi itu bukan submitule Git.
Ekosistem di sekitar keduanya juga dapat memengaruhi pilihan seseorang: Git harus lebih populer (tapi itu sepele), Git memiliki GitHub sementara Mercurial memiliki BitBucket , Mercurial memiliki TortoiseHg yang belum pernah saya lihat sama baiknya dengan Git.
Masing-masing memiliki kelebihan dan kekurangan, dengan salah satu dari mereka Anda tidak akan kehilangan.
sumber
Lihat pos Scott Chacon dari waktu yang lalu.
Saya pikir git memiliki reputasi sebagai "lebih rumit", meskipun dalam pengalaman saya itu tidak lebih rumit dari yang seharusnya. IMO, model git adalah cara lebih mudah untuk dipahami (tag berisi komit (dan pointer ke nol atau lebih komit induk) mengandung pohon berisi gumpalan dan pohon lainnya ... selesai).
Bukan hanya pengalaman saya bahwa git tidak lebih membingungkan daripada lincah. Saya akan merekomendasikan lagi membaca posting blog ini dari Scott Chacon tentang masalah ini.
sumber
.hgtags
ketika Anda telah memeriksa revisi 1.0. Namun, Anda tidak perlu mencari ke dalam.hgtags
dan Anda akan menemukan bahwahg tags
masih mencantumkan semua tag. Lebih jauh lagi, perilaku ini merupakan konsekuensi sederhana dari penyimpanan tag dalam file yang dikendalikan versi - lagi-lagi model ini mudah dipahami dan sangat dapat diprediksi .Saya telah menggunakan Git selama sedikit lebih dari setahun di pekerjaan saya saat ini, dan sebelumnya, menggunakan Mercurial selama lebih dari setahun di pekerjaan saya sebelumnya. Saya akan memberikan evaluasi dari sudut pandang pengguna.
Pertama, keduanya adalah sistem kontrol versi terdistribusi. Sistem kontrol versi terdistribusi membutuhkan perubahan pola pikir dari sistem kontrol versi tradisional, tetapi sebenarnya bekerja jauh lebih baik dalam banyak hal begitu orang memahaminya. Untuk alasan ini, saya menganggap Git dan Mercurial jauh lebih unggul daripada Subversion, Perforce, dll. Perbedaan antara sistem kontrol versi terdistribusi dan sistem kontrol versi tradisional jauh lebih besar daripada perbedaan antara Git dan Mercurial.
Namun, ada juga perbedaan signifikan antara Git dan Mercurial yang membuat masing-masing lebih cocok untuk subset kasus penggunaannya sendiri.
Mercurial lebih mudah dipelajari. Saya sampai pada titik di mana saya jarang harus merujuk pada dokumentasi atau catatan setelah beberapa minggu menggunakan Mercurial; Saya masih harus merujuk catatan saya secara teratur dengan Git, bahkan setelah menggunakannya selama satu tahun. Git jauh lebih rumit.
Ini sebagian karena Mercurial hanyalah pembersih biasa. Anda jarang harus bercabang secara manual di Mercurial; Mercurial akan membuat cabang anonim secara otomatis untuk Anda jika dan ketika Anda membutuhkannya. Nomenklatur mercurial lebih intuitif; Anda tidak perlu khawatir tentang perbedaan antara "ambil" dan "tarik" seperti yang Anda lakukan dengan Git. Mercurial sedikit kurang buggy. Ada masalah sensitivitas case name file yang digunakan untuk menyebabkan masalah saat mendorong proyek lintas platform dengan Git dan Mercurial; ini diperbaiki di Mercurial beberapa waktu lalu sementara mereka belum diperbaiki di Git terakhir saya periksa. Anda dapat memberi tahu Mercurial tentang penggantian nama file; dengan Git, jika ia tidak mendeteksi penggantian nama secara otomatis - proposisi yang sangat hit atau miss dalam pengalaman saya - ganti nama tidak dapat dilacak sama sekali.
Alasan lain untuk komplikasi tambahan Git, bagaimanapun, adalah bahwa sebagian besar dibutuhkan untuk mendukung fitur dan kekuatan tambahan. Ya, itu lebih rumit untuk menangani percabangan di Git - tetapi di sisi lain, begitu Anda memiliki cabang, tidak terlalu sulit untuk melakukan hal-hal dengan cabang-cabang yang hampir mustahil di Mercurial. Cabang rebasing adalah salah satu dari hal-hal ini: Anda dapat memindahkan cabang Anda sehingga basisnya, alih-alih menjadi keadaan batang saat Anda bercabang, adalah keadaan batang sekarang; ini sangat menyederhanakan riwayat versi ketika ada banyak orang yang bekerja pada basis kode yang sama, karena masing-masing dorongan untuk trunk dapat dibuat tampak berurutan, daripada saling terkait. Demikian pula, jauh lebih mudah untuk menciutkan banyak komit di cabang Anda menjadi satu komit,
Pada akhirnya saya pikir pilihan antara Mercurial dan Git harus bergantung pada seberapa besar proyek kontrol versi Anda, diukur berdasarkan jumlah orang yang mengerjakannya secara bersamaan. Jika Anda memiliki sekelompok selusin atau lebih yang bekerja pada aplikasi web monolitik tunggal, misalnya, alat manajemen cabang Git yang lebih kuat akan membuatnya lebih cocok untuk proyek Anda. Di sisi lain, jika tim Anda mengembangkan sistem terdistribusi heterogen, dengan hanya satu atau dua pengembang yang mengerjakan satu komponen pada satu waktu, menggunakan repositori Mercurial untuk setiap proyek komponen akan memungkinkan pengembangan berjalan lebih lancar dengan lebih sedikit overhead manajemen repositori.
Intinya: jika Anda memiliki tim besar yang mengembangkan satu aplikasi besar, gunakan Git; jika aplikasi individual Anda kecil, dengan skala apa pun yang berasal dari jumlah tersebut dan bukan dari ukuran aplikasi semacam itu, gunakan Mercurial.
sumber
Satu perbedaan yang sama sekali tidak terkait dengan DVCS sendiri:
Git tampaknya sangat populer di kalangan pengembang C. Git adalah repositori de-facto untuk Kernel Linux dan ini mungkin menjadi alasan mengapa ia sangat populer di kalangan pengembang C. Ini terutama berlaku bagi mereka yang memiliki kemewahan hanya bekerja di dunia Linux / Unix.
Pengembang Java tampaknya lebih menyukai Mercurial daripada Git. Mungkin ada dua alasan untuk itu: Pertama adalah bahwa sejumlah proyek Jawa yang sangat besar di-host di Mercurial, termasuk JDK itu sendiri. Lain adalah bahwa struktur dan dokumentasi yang bersih dari Mercurial menarik bagi orang-orang yang datang dari kamp Jawa sedangkan orang-orang seperti itu menemukan penamaan perintah git yang tidak konsisten dan kurang dalam dokumentasi Git. Saya tidak mengatakan itu sebenarnya benar, saya mengatakan orang sudah terbiasa dengan sesuatu dari habitat biasanya dan kemudian mereka cenderung memilih DVCS dari situ.
Pengembang python hampir secara eksklusif mendukung Mercurial, saya akan berasumsi. Sebenarnya tidak ada alasan rasional untuk itu selain fakta bahwa Mercurial didasarkan pada Python. (Saya menggunakan Mercurial juga dan saya benar-benar tidak mengerti mengapa orang-orang membuat keributan tentang bahasa implementasi DVCS. Saya tidak mengerti sepatah kata pun dari Python dan jika bukan karena fakta bahwa itu terdaftar di suatu tempat yang itu didasarkan pada Python maka saya tidak akan tahu).
Saya tidak berpikir Anda bisa mengatakan bahwa satu DVCS cocok dengan bahasa yang lebih baik daripada yang lain, jadi Anda tidak harus memilih itu. Tetapi pada kenyataannya orang memilih (sebagian) berdasarkan pada DVCS mana mereka paling terkena sebagai bagian dari komunitas mereka.
(tidak, saya tidak memiliki statistik penggunaan untuk mendukung klaim saya di atas .. itu semua berdasarkan pada subjektivitas saya sendiri)
sumber