Mudah untuk saya memahami cara Git commit dilaksanakan, tetapi sukar untuk memahami cara orang lain melihat commit. Jadi saya bertanya beberapa soalan kepada orang lain di Mastodon.
Saya menjalankan tinjauan yang sangat tidak saintifik yang bertanya kepada orang ramai tentang pendapat mereka tentang komitmen Git: adakah ia petikan, perbezaan atau senarai semua komitmen sebelumnya? (Sudah tentu, adalah munasabah untuk menganggapnya sebagai ketiga-tiganya, tetapi saya ingin tahu tentang perkara utama orang
Hasilnya ialah:
Saya terkejut betapa hampirnya nisbah kedua-dua pilihan dalam Perbezaan dan Syot Kilat. Orang ramai juga membuat beberapa perkara yang menarik tetapi bercanggah, seperti
"Nampaknya komit adalah satu perbezaan, tetapi saya fikir ia sebenarnya dilaksanakan sebagai petikan" dan
"Nampaknya komit adalah Gambar, tetapi saya rasa ia sebenarnya datang dalam bentuk perbezaan”. Kami akan bercakap lebih lanjut tentang cara penyerahan sebenarnya dilaksanakan kemudian.
Sebelum kita pergi lebih jauh: apakah yang kita maksudkan dengan "perbezaan" atau "gambar"?
"Perbezaan" yang saya maksudkan mungkin agak jelas: perbezaannya ialah apa yang anda dapat apabila anda berlari git show COMMIT_ID
. Sebagai contoh, berikut ialah pembetulan kesilapan menaip dalam projek rbspy:
diff --git a/src/ui/summary.rs b/src/ui/summary.rs index 5c4ff9c..3ce9b3b 100644 --- a/src/ui/summary.rs +++ b/src/ui/summary.rs @@ -160,7 +160,7 @@ mod tests { "; let mut buf: Vec = Vec::new(); -stats.write(&mut buf).expect("Callgrind write failed"); +stats.write(&mut buf).expect("summary write failed"); let actual = String::from_utf8(buf).expect("summary output not utf8"); assert_eq!(actual, expected, "Unexpected summary output"); }
Anda boleh melihatnya di GitHub: https://github.com/rbspy/rbspy/commit/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b
Dengan “snapshot” saya maksudkan “semua fail yang anda dapat apabila anda menjalankan git checkout COMMIT_ID
”.
Git biasanya merujuk kepada senarai fail yang diserahkan sebagai "pokok" (seperti "pokok direktori"), dan anda boleh melihat semua fail yang diserahkan di atas pada GitHub:
https://github.com/rbspy/rbspy/tree/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b (ia adalah /tree/
而不是 /commit/
)
Nasihat yang paling biasa saya dengar tentang pembelajaran Git mungkin "hanya pelajari cara Git mewakili sesuatu secara dalaman, dan semuanya akan menjadi lebih jelas". Saya jelas sangat menyukai perspektif ini (jika anda telah meluangkan sedikit masa membaca blog ini, anda akan tahu saya menyukainya
Tetapi sebagai cara untuk mempelajari Git, ia tidak menjadi seperti yang saya harapkan! Biasanya saya teruja mula menerangkan "Baiklah, jadi Git
komit ialah petikan, ia mempunyai penunjuk kepada komit induknya, kemudian cawangan adalah penunjuk kepada komit, kemudian...", tetapi saya cuba membantu Orang akan memberitahu saya bahawa mereka tidak benar-benar mendapati penjelasan itu berguna, bahawa mereka masih tidak memahaminya. Jadi saya telah melihat pilihan lain.
Tetapi mari kita bercakap tentang pelaksanaan dalaman dahulu.
Secara dalaman, Git mewakili komit sebagai syot kilat (ia menyimpan "pokok" versi semasa setiap fail). Saya berada dalam repositori Git, di manakah fail anda? Saya telah menulis tentang perkara ini dalam , tetapi berikut ialah gambaran keseluruhan yang sangat cepat tentang format dalaman.
Ini adalah perwakilan penyerahan:
$ git cat-file -p 24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b tree e197a79bef523842c91ee06fa19a51446975ec35 parent 26707359cdf0c2db66eb1216bf7ff00eac782f65 author Adam Jensen1672104452 -0500 committer Adam Jensen1672104890 -0500 Fix typo in expectation message
Dan, apabila kita melihat objek pokok ini, kita melihat senarai setiap fail/subdirektori di bawah akar repositori dalam komit ini:
$ git cat-file -p e197a79bef523842c91ee06fa19a51446975ec35 040000 tree 2fcc102acd27df8f24ddc3867b6756ac554b33ef.cargo 040000 tree 7714769e97c483edb052ea14e7500735c04713eb.github 100644 blob ebb410eb8266a8d6fbde8a9ffaf5db54a5fc979a.gitignore 100644 blob fa1edfb73ce93054fe32d4eb35a5c4bee68c5bf5ARCHITECTURE.md 100644 blob 9c1883ee31f4fa8b6546a7226754cfc84ada5726CODE_OF_CONDUCT.md 100644 blob 9fac1017cb65883554f821914fac3fb713008a34CONTRIBUTORS.md 100644 blob b009175dbcbc186fb8066344c0e899c3104f43e5Cargo.lock 100644 blob 94b87cd2940697288e4f18530c5933f3110b405bCargo.toml
Ini bermakna menyemak komit Git sentiasa pantas: ia sama mudah untuk Git menyemak komit semalam seperti menyemak komit sejuta yang lalu. Git tidak perlu memohon semula 10,000 diff untuk menentukan keadaan semasa kerana commit tidak pernah disimpan sebagai diff sama sekali.
Saya baru sahaja menyebut bahawa komit Git ialah petikan, tetapi apabila seseorang berkata "Pada pendapat saya, komit ialah petikan, tetapi saya fikir ia adalah perbezaan dalam pelaksanaan"
, itu sebenarnya benar juga! Git
commit tidak diwakili dalam bentuk diff yang mungkin anda biasa gunakan (ia tidak disimpan pada cakera sebagai beza daripada commit sebelumnya), tetapi intuisi asasnya ialah jika anda akan melakukan 10,000
fail baris Mengedit 500 kali, kemudian menyimpan 500 fail akan menjadi tidak cekap.
Git mempunyai cara untuk menyimpan fail sebagai perbezaan. Ini dipanggil "fail pek" dan Git akan mengumpul data anda secara berkala ke dalam fail pek untuk menjimatkan ruang cakera. Git juga memampatkan data apabila anda git clone
repositori.
Saya tidak mempunyai ruang yang mencukupi di sini untuk menerangkan sepenuhnya cara fail pek berfungsi ("Membongkar fail pek Git" Aditya Mukerjee ialah artikel kegemaran saya untuk menerangkan cara ia berfungsi). Walau bagaimanapun, saya boleh merumuskan secara ringkas pemahaman saya tentang cara delta berfungsi dan cara ia berbeza daripada perbezaan di sini:
Apa yang sebenarnya berlaku apabila kita berlari git show SOME_COMMIT
untuk melihat perbezaan komit adalah sedikit intuitif. Pemahaman saya ialah:
Jadi, Git akan menukarkan perubahan kepada syot kilat dan kemudian mengira perbezaannya. Rasanya agak pelik kerana ia bermula dengan sesuatu seperti perbezaan dan berakhir dengan perkara lain seperti perbezaan, tetapi jumlah perubahan dan perbezaan itu sebenarnya berbeza sama sekali, jadi ia masuk akal.
Yang berkata, saya rasa Git stores commit sebagai syot kilat dan fail pek hanyalah butiran pelaksanaan untuk menjimatkan ruang cakera dan mempercepatkan pengklonan. Saya sebenarnya tidak perlu tahu cara fail pack berfungsi, tetapi ia membantu saya memahami cara syot kilat Git dilakukan tanpa mengambil terlalu banyak ruang cakera.
Saya rasa pemahaman yang agak biasa tentang "kesilapan" Git ialah:
Pemahaman ini sudah tentu salah (sebenarnya, commit disimpan dalam bentuk syot kilat dan perbezaan dikira daripada syot kilat ini), tetapi bagi saya ia kelihatan sangat berguna dan masuk akal! Agak pelik apabila memikirkan tentang merge commit, tetapi mungkin kita boleh mengatakan bahawa ini hanyalah perbezaan berdasarkan commit induk pertama bagi merge commit.
Saya rasa salah faham ini kadangkala sangat berguna, dan ia nampaknya tidak menjadi masalah untuk penggunaan Git harian. Saya sangat suka bahawa ia menjadikan perkara yang paling banyak kita gunakan (perbezaan) sebagai elemen paling asas - ia sangat intuitif kepada saya.
Saya juga telah memikirkan beberapa pemahaman lain yang berguna tetapi "salah" tentang Git, seperti:
Saya rasa terdapat pelbagai pemahaman "salah" tentang Git yang sangat masuk akal, sebahagian besarnya disokong oleh antara muka pengguna Git, dan tidak menyebabkan masalah dalam kebanyakan kes. Tetapi ia boleh mengelirukan apabila anda ingin membuat asal perubahan atau berlaku masalah.
Walaupun saya tahu commit ialah syot kilat dalam Git, saya mungkin menganggapnya sebagai berbeza pada kebanyakan masa kerana:
git show
jadi ia adalah sesuatu yang biasa saya lihat Tetapi saya juga kadangkala menganggap commit sebagai syot kilat kerana:
git checkout COMMIT_ID
lakukan (idea memohon semula 10,000 komitmen membuatkan saya tertekan) Beberapa balasan Mastodon juga menyebut:
Beberapa perkataan lain yang digunakan orang apabila bercakap tentang komitmen yang mungkin kurang samar-samar:
Sukar untuk saya memahami perbezaan pemahaman orang tentang Git. Apa yang lebih rumit ialah, walaupun pemahaman "salah" selalunya sangat berguna, orang ramai sangat berminat untuk berhati-hati dengan model mental yang "salah" sehingga mereka enggan berkongsi idea "salah" mereka kerana bimbang sesetengah jurubahasa Git akan berdiri. Keluar dan terangkan kepada mereka mengapa mereka salah. (Penerjemah Git
ini biasanya bermaksud baik, tetapi ia boleh memberi kesan negatif tanpa mengira)
Terima kasih kepada Marco Rogers, Marie Flanagan dan semua orang di Mastodon kerana membincangkan komitmen Git dengan saya.
Atas ialah kandungan terperinci Adakah Git melakukan perbezaan, syot kilat atau sejarah?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!