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
- Struktur repositori: Mercurial tidak mengizinkan penggabungan gurita (dengan lebih dari dua orang tua), atau menandai objek yang tidak berkomitmen.
- Tag: Mercurial menggunakan
.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 di refs/tags/
namespace, dan secara default diikutkan secara otomatis pada pengambilan dan memerlukan dorongan eksplisit.
- Cabang: Dalam alur kerja dasar Mercurial didasarkan pada kepala anonim ; Git menggunakan cabang bernama ringan, dan memiliki jenis cabang khusus ( cabang pelacakan jarak jauh ) yang mengikuti cabang di repositori jarak jauh.
- Penamaan dan rentang revisi : Mercurial memberikan angka revisi , lokal ke repositori, dan mendasarkan revisi relatif (dihitung dari ujung, yaitu cabang saat ini) dan rentang revisi pada penomoran lokal ini ; Git menyediakan cara untuk merujuk pada revisi relatif terhadap ujung cabang, dan rentang revisi bersifat topologis (berdasarkan grafik revisi)
- Mercurial menggunakan pelacakan nama , sedangkan Git menggunakan deteksi nama untuk berurusan dengan nama file
- Jaringan: Mercurial mendukung protokol SSH dan HTTP "pintar", dan protokol HTTP statis; Git modern mendukung protokol SSH, HTTP, dan GIT "pintar", dan protokol HTTP (S) "bodoh". Keduanya memiliki dukungan untuk file bundel untuk transportasi off-line.
- Mercurial menggunakan ekstensi (plugin) dan API yang mapan; Git memiliki skripabilitas dan format yang ditetapkan.
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 oleh git bisect
perintah di Git, sementara ide git bundle
diilhami oleh hg 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 dalam refs/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 dalam refs/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
atau tags
, misalnya local-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 menggunakan hg 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 (dari refs/heads/
namespace), dan menyimpannya di refs/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 ):
- Nama objek SHA1 lengkap (string heksadesimal 40-byte), atau substring sedemikian rupa sehingga unik dalam repositori
- Nama referensi simbolis, misalnya 'master' (merujuk ke cabang 'master'), atau 'v1.5.0' (merujuk ke tag), atau 'asal / depan' (merujuk ke cabang pelacakan jarak jauh)
^
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'
- Output dari "git menggambarkan", yaitu tag terdekat, opsional diikuti oleh tanda hubung dan sejumlah komit, diikuti oleh tanda hubung, a 'g', dan nama objek disingkat, misalnya 'v1.6.5.1-75- g5bf8097 '.
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 ):
- Bilangan bulat biasa diperlakukan sebagai angka revisi. Kita harus ingat bahwa angka revisi adalah lokal untuk repositori yang diberikan ; di repositori lain mereka bisa berbeda.
- Bilangan bulat negatif diperlakukan sebagai offset berurutan dari ujung, dengan -1 menunjukkan ujung, -2 menunjukkan revisi sebelum ujung, dan sebagainya. Mereka juga lokal untuk repositori.
- Pengidentifikasi revisi unik (string heksadesimal 40 digit) atau awalan uniknya.
- Nama tag (nama simbolis yang terkait dengan revisi yang diberikan), atau nama bookmark (dengan ekstensi: nama simbolis terkait dengan kepala yang diberikan, lokal ke repositori), atau "cabang bernama" (label komit; revisi diberikan oleh "cabang bernama" adalah tip (komitmen tanpa anak) dari semua komitmen dengan label komit yang diberikan, dengan nomor revisi terbesar jika ada lebih dari satu tip seperti itu)
- "Tip" nama yang dicadangkan adalah tag khusus yang selalu mengidentifikasi revisi terbaru.
- Nama yang dicadangkan "null" menunjukkan revisi nol.
- Nama yang dicadangkan "." menunjukkan induk direktori kerja.
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 perilaku A..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 tentang A...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 berarti A 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 menjalankan hg 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 di git 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:
- Protokol "pintar" , yang mencakup akses melalui SSH dan melalui custom git: // protocol (by
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".
- Protokol "bodoh" , yang meliputi HTTP dan FTP (hanya untuk mengambil), dan HTTPS (untuk mendorong melalui WebDAV), tidak memerlukan git yang diinstal pada server, tetapi protokol tersebut mengharuskan repositori berisi informasi tambahan yang dihasilkan oleh
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