Mengapa git menggunakan hash alih-alih angka revisi?

80

Saya selalu bertanya-tanya mengapa git lebih suka hash daripada angka revisi. Angka revisi jauh lebih jelas dan lebih mudah untuk dirujuk (menurut saya): Ada perbedaan antara menyuruh seseorang untuk melihat revisi 1200 atau melakukan 92ba93e! (Sekedar memberi satu contoh).

Jadi, apakah ada alasan untuk desain ini?

Max Beikirch
sumber
3
Anda bisa menandai komit dengan "v1.0" dan kemudian merujuk komit dengan tag itu. Lihat git-scm.com/book/en/v2/Git-Basics-Tagging
Michael Durrant

Jawaban:

114

Angka revisi tunggal yang meningkat secara monoton hanya benar-benar masuk akal untuk sistem kontrol versi terpusat, di mana semua revisi mengalir ke satu tempat yang dapat melacak dan menetapkan angka. Setelah Anda masuk ke dunia DVCS, di mana banyak salinan repositori ada dan perubahan ditarik dari dan didorong ke mereka dalam alur kerja yang sewenang-wenang, konsep itu tidak berlaku. (Misalnya, tidak ada satu tempat untuk menetapkan angka revisi - jika saya membayar repositori Anda dan Anda memutuskan setahun kemudian untuk menarik perubahan saya, bagaimana sistem memastikan bahwa angka revisi kami tidak bertentangan?)

Josh Kelley
sumber
11
Anda mungkin ingin melihat cara Bazaar - sebuah DVCS yang masih mempertahankan angka revisi. Satu-satunya jaminan di sana adalah nomor revisi unik di dalam cabang.
krlmlr
3
@ krlmlr Person 1: "Hey, <P2>, what was revision 12345 for?" P2: "Revision 12345 was commited by <P3>." P3: "I don't have a revision 12345..."- Jika saya ingat dengan benar, Mercurial memiliki masalah serupa. Di sisi lain, jika mereka menggunakan git, mereka semua akan memiliki referensi yang identik untuk setiap komit.
Izkata
1
@Izkata: P1: "Do you have revision with the GUID gdlmsnblngoijlafd-35345-fg?"... Bazaar masih memiliki GUID ...
krlmlr
5
@Izkata Mercurial tidak memiliki masalah serupa. Mereka menggunakan hash, sama seperti git. Mereka juga memberikan nomor rev hanya lokal untuk kemudahan mengetik.
Hank Gay
1
dengan git, 5 karakter pertama dari hash seringkali cukup unik untuk menggunakan singkatan untuk ID revisi penuh.
mendota
40

Anda memerlukan hash dalam sistem terdistribusi. Katakanlah Anda dan seorang kolega sedang mengerjakan repositori yang sama dan Anda berdua melakukan perubahan secara lokal lalu mendorongnya. Siapa yang akan menjadi revisi nomor 1200 dan siapa yang revisi nomor 1201 diberikan tidak ada pihak yang memiliki pengetahuan tentang satu sama lain? Satu-satunya solusi teknis yang realistis adalah membuat hash dari perubahan menggunakan metode yang dikenal dan menghubungkan semuanya berdasarkan itu.

Menariknya HG memang mendukung nomor versi tetapi mereka secara eksplisit merupakan fitur hanya-lokal - repositori Anda memiliki satu set, repo rekan kerja Anda akan memiliki set yang berbeda tergantung pada bagaimana mereka mendorong dan menarik. Itu membuat penggunaan baris perintah sedikit lebih ramah daripada Git.

Wyatt Barnett
sumber
34

Integritas data.

Saya dengan hormat tidak setuju dengan jawaban saat ini. Hash tidak diperlukan untuk DVCS, lihat cara Bazaar . Anda juga dapat melakukannya dengan jenis pengenal unik global lainnya. Hash adalah ukuran untuk menjamin integritas data: Mereka mewakili intisari informasi yang terkandung dalam objek (komit, pohon, ...) yang dirujuk oleh hash. Mengubah konten tanpa mengubah hash (yaitu, serangan preimage atau serangan tabrakan ) diyakini sulit, meskipun bukan tidak mungkin. (Jika Anda benar-benar menyukainya, lihatlah makalah 2011 karya Marc Stevens ).

Oleh karena itu, merujuk pada objek dengan hash SHA mereka memungkinkan untuk memeriksa apakah isinya telah dirusak. Dan, mengingat bahwa mereka (hampir) dijamin unik, mereka juga dapat digunakan sebagai pengidentifikasi revisi - sangat mudah.

Lihat Bab 9 dari buku Git untuk lebih jelasnya.

krlmlr
sumber
8
Ini bukan ukuran keamanan, karena hash dapat dengan mudah dihitung ulang untuk komit yang dimodifikasi. Ini hanya digunakan untuk integritas, untuk memverifikasi konten terhadap hash yang dihitung - lihat komentar ini dari Linus Torvalds tentang penggunaan SHA-1 di Git.
Lee
@ Lee: Jika repositori Chuck berbeda dari yang dimiliki Alice dan Bob dalam hal hash revisi, dijamin Chuck juga memiliki konten yang berbeda. Di sisi lain, sangat sulit bagi Chuck untuk membuat repositori dengan konten berbeda yang terlihat identik dengan hash revisi mereka.
krlmlr
@Lee: Link Anda terlewatkan. Sebut saja "integritas data" lalu ...
krlmlr
seharusnya jawaban yang benar
SuperUberDuper
8

Dalam kata-kata awam:

  • Hash dimaksudkan untuk menjadi hampir universal unik. Ini TIDAK dijamin tetapi sangat tidak mungkin SHA yang sama dihasilkan untuk konten yang berbeda. Dalam istilah praktis untuk proyek tertentu Anda dapat menganggapnya unik.
  • Dengan angka revisi Anda harus menggunakan namespace untuk merujuk secara khusus ke revisi 1200.
  • Git dapat bekerja baik secara terdistribusi dan / atau terpusat. Jadi, bagaimana Anda mendapatkan angka revisi yang benar dan unik?
  • Juga menggunakan angka revisi akan menciptakan spektasi palsu bahwa revisi yang lebih baru harus memiliki angka yang lebih tinggi, dan itu tidak akan benar karena percabangan, penggabungan, rebasing, dll.
  • Anda selalu memiliki opsi untuk menempatkan tag untuk dikomit.
Tulains Córdova
sumber
32
Tidak dijamin unik, hanya sangat mungkin unik. :)
dsw88
@ mustang2009cobra Itu benar.
Tulains Córdova
1
Mungkin saja perubahan saya tidak diterima karena hash tidak berubah. Jauh lebih mungkin bahwa dua meteor menyerang komputer saya dan komputer dengan repositori pada saat yang sama, menghancurkan komputer dan membunuh semua orang yang terlibat.
gnasher729
1

Hash bukan solusi unik untuk VCS terdistribusi. Tetapi ketika berhadapan dengan sistem terdistribusi, hanya pemesanan sebagian acara yang dapat dicatat. (Untuk VCS, acara tersebut dapat berupa komit.) Itulah mengapa mempertahankan angka revisi yang monoton mustahil dilakukan. Biasanya kita mengadopsi sesuatu seperti jam vektor (atau stempel waktu vektor) untuk merekam hubungan yang dipesan sebagian itu. Ini adalah solusi yang digunakan di Bazaar .

Tapi mengapa Git tidak menggunakan jam vektor tapi hash? Saya pikir akar penyebabnya adalah cherry-pick . Ketika kami melakukan cherry-pick pada repositori, pemesanan sebagian dari commit berubah. Jam vektor beberapa commit harus ditugaskan ulang untuk mewakili pemesanan parsial baru. Namun, penugasan kembali seperti itu dalam sistem terdistribusi akan menyebabkan jam vektor tidak konsisten. Itu adalah masalah nyata yang berhubungan hash.

Che-Sheng Lin
sumber