Terlepas dari kenyataan bahwa GIT TIDAK menyimpan delta file, dapatkah Anda tetap mengembalikan ke versi file sebelumnya (waktu yang tidak terbatas?)

14

Saya pernah membaca bahwa Git tidak menyimpan file delta. Jika ini benar, bagaimana ini mendukung pengembalian file ke versi sebelumnya? Jika menyimpan seluruh file, ruang repositori pada disk harus tumbuh menjadi tidak terkelola. Apakah Git mendukung pengembalian dan perbedaan file kembali ke file versi 1? Apakah bahkan mendukung konsep versi yang terkait dengan file? Ini (saya percaya) penting untuk pemahaman saya tentang VCS / DVCS dan kebutuhan saya. Saya harus dapat membandingkan apa yang akan saya periksa dengan versi sebelumnya.

Pete Alvin
sumber

Jawaban:

44

Git tidak membuang informasi sendiri *. Semua versi sebelumnya dari setiap file selalu tersedia untuk pengembalian, perbedaan, inspeksi, dan sebagainya.

Pohon utuh versus file individu

Apa yang Anda coba rekonsiliasi adalah gagasan untuk mengakses versi lama dari file individual versus fakta bahwa model sejarah Git terfokus pada keseluruhan pohon. Versi Whole-tree memang membutuhkan sedikit lebih banyak pekerjaan untuk melihat (misalnya) versi foo.cseperti yang ada sepuluh- foo.cperubahan lalu versus sepuluh seluruh-pohon-perubahan yang lalu:

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

Manfaat orientasi pohon, terutama kemampuan untuk melihat commit sebagai unit perubahan yang saling tergantung yang dibuat untuk berbagai bagian dari keseluruhan pohon, secara umum lebih besar daripada mengetik tambahan (yang dapat dikurangi dengan alias, skrip, dan lain-lain) dan waktu CPU dihabiskan menggali melalui komitmen masa lalu.

Efisiensi Penyimpanan

Ketika objek baru (misalnya file dengan konten yang sebelumnya tidak terlihat) memasuki sistem, ia disimpan dengan kompresi polos (zlib) sebagai "objek longgar". Ketika cukup banyak benda longgar terakumulasi (berdasarkan gc.autoopsi konfigurasi; atau ketika pengguna menjalankan git gc atau salah satu dari perintah pengemasan tingkat rendah), Git akan mengumpulkan banyak benda lepas ke dalam satu "file paket".

Objek dalam file paket dapat disimpan baik sebagai data terkompresi biasa (sama seperti objek longgar, hanya dibundel dengan objek lain), atau sebagai delta terkompresi terhadap beberapa objek lain. Delta dapat dirantai bersama ke kedalaman yang dapat dikonfigurasi ( pack.depth) dan dapat dibuat terhadap objek yang cocok ( pack.windowmengontrol seberapa luas Git mencari basis delta terbaik; versi file yang tidak terkait secara historis dapat digunakan sebagai basis jika melakukan hal itu akan menghasilkan suatu kompresi delta yang baik). Garis lintang yang diberikan oleh konfigurasi kedalaman dan ukuran jendela mesin kompresi delta sering menghasilkan kompresi delta yang lebih baik daripada kompresi "diff" satu-versi-gaya-lawan-versi-berikutnya / versi sebelumnya yang sebelumnya.

Ini adalah kompresi delta agresif (dikombinasikan dengan kompresi zlib normal) yang sering dapat membiarkan repositori Git (dengan sejarah penuh dan pohon kerja yang tidak terkompresi) mengambil lebih sedikit ruang daripada checkout SVN tunggal (dengan pohon kerja yang tidak terkompresi dan salinan asli).

Lihat bagian Bagaimana Git Menyimpan Objek dan Paket Packfile dari Buku Komunitas Git . Juga manpage paket-objek git .

* Anda dapat memberi tahu Git membuang komit dengan "menulis ulang sejarah" dan dengan perintah seperti git reset , tetapi bahkan dalam kasus ini Git "menggantung" komit yang baru dibuang untuk sementara waktu, kalau-kalau Anda memutuskan Anda membutuhkannya. Lihat git reflog dan git pangkas .

Chris Johnsen
sumber
3
+1 hanya untuk jumlah dan detail informasi yang Anda berikan.
Tamara Wijsman
3
Juga, karena Git menggunakan snapshot file daripada delta, kembali jauh dalam sejarah sebenarnya lebih mudah. Bayangkan Anda perlu melihat file dari 20 komit yang lalu. Dengan delta, Anda harus membatalkan 20 perubahan; dengan snapshot, Anda hanya mengambil snapshot yang tepat. Semakin lama sejarah Anda, semakin besar keuntungannya. Dan jika Anda ingin melihat perbedaan antara versi saat ini dan yang satu, itu hanya perbedaan tunggal, daripada harus memutuskan apa yang telah dilakukan, dibatalkan, diulang, dll.
Nathan Long
Chris, Anda tampaknya memiliki pegangan yang bagus pada internal Git. Apakah ada kemungkinan Anda bisa melakukan ini? stackoverflow.com/questions/5176225/…
Nathan Long
@ ChrisJohnsen Tolong bantu saya memahami ini. Berdasarkan apa yang Anda katakan, bisakah Git mendapatkan efisiensi penyimpanan yang serupa (atau lebih baik) daripada Subversion? Saya tahu bahwa jika saya mengkomit file dengan sedikit perubahan berkali-kali, data senilai 1GB dapat disimpan dalam 100MB. Bisakah Git melakukan hal yang sama?
Alireza Noori
@AlirezaNoori: Semuanya tergantung pada sifat data dan perubahan yang ditangkap (ukuran file, kompresibilitas file, ukuran dan lokasi perubahan, dll.). Sesuatu seperti itu tentunya harus dimungkinkan (tergantung spesifik). Secara umum, file paket Git dapat menggambar dari pilihan basis yang lebih besar untuk kompresi delta dibandingkan dengan delta kronologis reverse-ketat yang digunakan server SVN (digunakan? Saya tidak mengikuti pengembangan SVN ...). Jika Anda memiliki beberapa pertanyaan spesifik, Anda harus mempertimbangkan untuk mengajukan pertanyaan baru yang mencakup semua perincian terkait.
Chris Johnsen
1

Itu bisa dibaca di halaman yang sama:

...

Akibatnya, Git tidak secara eksplisit merekam hubungan revisi file pada tingkat apa pun di bawah pohon kode sumber.

...

Sedikit lebih mahal untuk memeriksa riwayat perubahan satu file daripada keseluruhan proyek. Untuk mendapatkan riwayat perubahan yang mempengaruhi file yang diberikan, Git harus mengikuti sejarah global dan kemudian menentukan apakah setiap perubahan memodifikasi file itu. Metode memeriksa riwayat ini, bagaimanapun, membiarkan Git menghasilkan dengan efisiensi yang sama satu sejarah menunjukkan perubahan ke set file sewenang-wenang. Sebagai contoh, subdirektori dari pohon sumber ditambah file header global terkait adalah kasus yang sangat umum.

...

Dengan demikian Anda dapat kembali ke revisi file sebelumnya dan membandingkan dua file.

Tamara Wijsman
sumber
1

git memang menyimpan delta file, tetapi menyimpannya sebagai delta seluruh pohon file.

Untuk melihat perbedaan antara versi, lakukan salah satu dari yang berikut:

  1. diff git - menunjukkan perbedaan antara versi yang terakhir diperiksa dan file yang telah diubah, tetapi belum pernah git adddijalankan.
  2. git diff --cached - menunjukkan perbedaan antara versi sebelumnya dan semua file yang telah git adddijalankan, tetapi belum dikomit
  3. git diff commitid - menunjukkan perbedaan antara direktori kerja saat ini dan komit sebelumnya seperti yang ditentukan dengan komit
  4. git diff commita..commitb - menunjukkan perbedaan antara dua commit, a dan b. Komit juga bisa berupa nama simbolis seperti cabang atau tag.
edgester
sumber
Jawaban ini tidak sepenuhnya benar. Semua perintah itu dapat diterapkan ke set file yang sewenang-wenang serta seluruh pohon - tambahkan saja nama file di akhir ...
naught101