Apa yang sebenarnya dilakukan git ketika dikatakan "menyelesaikan delta"?

187

Selama klon pertama repositori, git pertama menerima objek (yang cukup jelas), dan kemudian menghabiskan waktu yang sama untuk "menyelesaikan delta". Apa yang sebenarnya terjadi selama fase kloning ini?

Nik Reiman
sumber
Terkait: stackoverflow.com/questions/9478023/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件
1
Lihat juga, untuk Git 2.20 (Q4 2018) dan lebih banyak pulau delta: stackoverflow.com/a/52458712/6309
VonC

Jawaban:

54

Git menggunakan delta encoding untuk menyimpan beberapa objek dalam paket file. Namun, Anda tidak ingin harus bermain kembali setiap perubahan tunggal yang pernah pada file yang diberikan untuk mendapatkan versi saat ini, sehingga Git juga memiliki snapshot sesekali isi file yang disimpan juga. "Menyelesaikan delta" adalah langkah yang berhubungan dengan memastikan semua itu tetap konsisten.

Inilah bab dari bagian "Git Internal" dari buku Pro Git, yang tersedia online, yang membahas tentang ini.

Amber
sumber
80
Jawaban ini salah. Tampaknya menggambarkan bagaimana Mercurial bekerja, bukan Git. Itu muncul dalam pencarian Google untuk masalah ini jadi saya merasa perlu untuk membalas. Git tidak menyimpan perbedaan antara commit sebagai delta; Git adalah toko "seluruh objek". Dengan demikian, Git tidak perlu "snapshots" untuk menampilkan file yang diberikan karena riwayat file tidak perlu direkonstruksi dari delta. Begitulah cara Mercurial bekerja.
nexus mengatakan
12
Satu-satunya tempat di mana pengkodean delta mulai dimainkan adalah dalam file paket yang hanya untuk kompresi dan transfer - itu tidak mengubah cara Git "melihat" dunia. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Silakan lihat jawaban araqnid di bawah ini untuk respons yang akurat.
nexus mengatakan
4
Semua "snapshot" berarti dalam konteks ini adalah salinan lengkap dari status file, bukan versi yang dikodekan delta. Seperti yang Anda sebutkan, Git tidak menggunakan delta-encoding di packfiles. Tidak ada yang mengatakan bahwa "mengubah cara Git melihat dunia"; tolong hentikan proyeksi asumsi Anda sendiri.
Amber
2
Jawaban Anda masih tidak akurat. "Git juga memiliki snapshot sesekali dari isi file yang disimpan juga." - itu tidak benar. "'Menyelesaikan delta' adalah langkah yang berhubungan dengan memastikan semua itu tetap konsisten." - itu juga tidak benar, respons araqnid di bawah ini benar.
nexus mengatakan
1
Seperti dijelaskan dalam bab yang disebutkan di atas, Git selalu menyimpan konten file lengkap dari versi terbaru. Versi sebelumnya disimpan sebagai file berkode delta ketika file tersebut "longgar". Secara berkala (baik dengan menelepon git gcatau kapan pun Git menentukannya perlu) Git akan mengompres semua file "longgar" ke dalam paketfile untuk menghemat ruang dan file indeks ke dalam paketf tersebut akan dibuat. Jadi zlib akan mengompres dengan algoritma delta sendiri tetapi Git menggunakan delta-encoding untuk menyimpan versi sebelumnya. Karena akses yang paling umum dan sering adalah versi terbaru, itu disimpan sebagai snapshot.
BrionS
118

Tahapannya git cloneadalah:

  1. Menerima file "paket" dari semua objek dalam database repo
  2. Buat file indeks untuk paket yang diterima
  3. Lihat revisi head (untuk repo non-telanjang, jelas)

"Resolving delta" adalah pesan yang ditunjukkan untuk tahap kedua, mengindeks file paket ("git index-pack").

File paket tidak memiliki ID objek aktual di dalamnya, hanya konten objek. Jadi untuk menentukan apa ID objek, git harus melakukan dekompresi + SHA1 dari setiap objek dalam paket untuk menghasilkan ID objek, yang kemudian ditulis ke dalam file indeks.

Objek dalam file paket dapat disimpan sebagai delta yaitu urutan perubahan yang dibuat ke beberapa objek lain. Dalam hal ini, git perlu mengambil objek dasar, menerapkan perintah dan SHA1 hasilnya. Objek dasar itu sendiri mungkin harus diturunkan dengan menerapkan urutan perintah delta. (Meskipun dalam kasus kloning, objek dasar sudah akan ditemui, ada batas berapa banyak objek yang diproduksi di-cache dalam memori).

Singkatnya, tahap "menyelesaikan delta" melibatkan dekompresi dan checksumming seluruh database repo, yang tidak mengejutkan membutuhkan waktu yang cukup lama. Agaknya dekompresi dan penghitungan SHA1 sebenarnya membutuhkan lebih banyak waktu daripada menerapkan perintah delta.

Dalam kasus pengambilan berikutnya, file paket yang diterima dapat berisi referensi (sebagai basis objek delta) ke objek lain yang diharapkan sudah dimiliki oleh git penerima. Dalam hal ini, git penerima sebenarnya menulis ulang file paket yang diterima untuk menyertakan objek yang direferensikan tersebut, sehingga setiap file paket yang disimpan cukup mandiri. Di sinilah pesan "resolta delta" berasal.

araqnid
sumber
7
Bisakah ini diparalelkan?
brooksbp
Apakah kompresi delta ini lebih dari menyimpan beberapa objek dalam satu aliran data zlib?
fuz
1
@ FuZxxl ya, itu menggunakan algoritma seperti diff atau xdelta untuk membandingkan dua gumpalan dan menghasilkan naskah edit
araqnid
@brooksbp: Hanya dengan batasan. Karena objek dengan id 103fa49 mungkin perlu df85b51 untuk diterjemahkan, tetapi ketika Anda menerima 103fa49, df85b51 belum ada di sana (file paket secara ketat dipesan oleh sha1 hashes). Jadi, untuk semua yang merujuk hanya barang-barang yang sudah ada di sana, segalanya mudah, tetapi untuk semua yang lain, Anda harus menunggu sampai diterima. Dan kompresi delta ini dapat disarangkan, sehingga 103fa49 mungkin membutuhkan 4e9ba42 yang pada gilirannya membutuhkan 29ad945 yang pada gilirannya membutuhkan c9e645a ... Anda mendapatkan gambarnya. [ya, saya perhatikan sudah> 4 tahun;)]
Bodo Thiesen
2
@brooksbp: Ternyata, saya salah, file paket TIDAK perlu diurutkan berdasarkan hash sha1. Juga, ketika menulis, git menulis objek yang diperlukan sebelum objek membutuhkannya. Jadi, sebenarnya Anda harus bisa memparalelkannya. Hanya kerugian yang tersisa: Karena Anda tidak tahu objek mana yang akan Anda perlukan nanti, Anda harus membuat ulang beberapa objek berulang-ulang. Lihat di sini: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen
4

Amber tampaknya menggambarkan model objek yang Mercurial atau gunakan serupa. Git tidak menyimpan delta di antara versi berikutnya dari suatu objek, melainkan snapshot objek yang penuh, setiap saat. Ini kemudian mengkompresi snapshot ini menggunakan kompresi delta, mencoba mencari delta yang baik untuk digunakan, terlepas dari mana dalam sejarah ini ada.

Johan
sumber
5
Sebenarnya, sementara Git dapat menyimpan objek yang longgar, mereka tidak harus selalu disimpan seperti itu - karena objek yang longgar dapat dihapus dan diganti dengan konten yang dikemas. Saya tidak berpikir jawaban Amber mengatakan apa pun tentang versi berikutnya.
AlBlue