git เก็บไฟล์ได้อย่างไร?


225

ฉันเพิ่งเริ่มเรียนรู้คอมไพล์และฉันก็เริ่มอ่านหนังสือชุมชน Gitและในหนังสือเล่มนี้พวกเขาบอกว่า SVN และ CVS เก็บความแตกต่างระหว่างไฟล์และ git นั้นเก็บสแน็ปช็อตของไฟล์ทั้งหมด

แต่ฉันไม่ได้รับสิ่งที่พวกเขาหมายถึงโดยภาพรวม คอมไพล์ทำสำเนาไฟล์ทั้งหมดในแต่ละคอมมิทหรือไม่เพราะนั่นคือสิ่งที่ฉันเข้าใจจากคำอธิบายของมัน

ป.ล. : ถ้ามีใครมีแหล่งที่ดีกว่าที่จะเรียนรู้คอมไพล์ฉันจะขอบคุณมัน


20
นี่คือโพสต์ที่ยอดเยี่ยมที่อธิบายรายละเอียดวิธีการทำงานของ git สิ่งที่คุณกำลังค้นหาน่าจะเป็น the เกี่ยวกับฐานข้อมูลวัตถุ
greg0ire

บทความที่ยอดเยี่ยมที่มีลิงค์ไปยังแหล่งข้อมูลที่ดีอื่น ๆ ฉันสนุกกับสิ่งเหล่านี้สองสามชั่วโมง
mihai

2
ฉันพบบทความที่ดีจริง ๆ นี้อธิบาย git จากภายในสู่ภายนอก: maryrosecook.com/blog/post/git-from-the-inside-out
Sumudu

คำตอบ:


275

Git รวมไว้สำหรับการส่งสำเนาไฟล์ทั้งหมดยกเว้นว่าสำหรับเนื้อหาที่มีอยู่แล้วใน repo Git สแน็ปช็อตจะชี้ไปที่เนื้อหาดังกล่าวแทนที่จะทำซ้ำ
นั่นหมายความว่าไฟล์หลาย ๆ ไฟล์ที่มีเนื้อหาเดียวกันจะถูกจัดเก็บเพียงครั้งเดียว

ดังนั้นสแนปชอตจึงเป็นคอมมิทคอมอ้างถึงเนื้อหาของโครงสร้างไดเรกทอรี

อ้างอิงที่ดีคือ:

คุณบอก Git ว่าคุณต้องการบันทึกสแนปชอตของโครงการของคุณด้วยคำสั่ง Git และมันจะบันทึกรายการไฟล์ทั้งหมดในโปรเจ็กต์ของคุณว่าเป็นอย่างไร

แล็บ 12แสดงวิธีรับสแนปชอตก่อนหน้า


หนังสือ progitมีคำอธิบายที่ครอบคลุมมากขึ้นของภาพ:

ความแตกต่างที่สำคัญระหว่าง Git และ VCS อื่น ๆ (รวมถึงการโค่นล้มและเพื่อน) คือวิธีที่ Git คิดเกี่ยวกับข้อมูล
ตามแนวคิดแล้วระบบอื่น ๆ ส่วนใหญ่จะจัดเก็บข้อมูลเป็นรายการของการเปลี่ยนแปลงตามไฟล์ ระบบเหล่านี้ (CVS, การโค่นล้ม, Perforce, Bazaar และอื่น ๆ ) คิดว่าข้อมูลที่พวกเขาเก็บไว้เป็นชุดของไฟล์และการเปลี่ยนแปลงที่เกิดขึ้นกับแต่ละไฟล์ในช่วงเวลาหนึ่ง

VCS ที่ใช้เดลต้า

Git ไม่คิดหรือเก็บข้อมูลด้วยวิธีนี้ แต่ Git คิดถึงข้อมูลมากกว่าชุดของสแน็ปช็อตของระบบไฟล์ขนาดเล็กแทน
ทุกครั้งที่คุณคอมมิชชันหรือบันทึกสถานะโครงการของคุณใน Git โดยทั่วไปแล้วจะถ่ายภาพว่าไฟล์ของคุณทั้งหมดเป็นอย่างไรในขณะนั้นและเก็บการอ้างอิงไปยังสแน็ปช็อตนั้น
เพื่อให้มีประสิทธิภาพหากไฟล์ไม่เปลี่ยนแปลง Git จะไม่จัดเก็บไฟล์อีก - เพียงแค่ลิงค์ไปยังไฟล์ที่เหมือนกันก่อนหน้านี้ซึ่งมันถูกเก็บไว้แล้ว
Git คิดเกี่ยวกับข้อมูลของตนดังนี้:

VCS ที่ยึดตามสแน็ปช็อต

นี่คือความแตกต่างที่สำคัญระหว่าง Git และ VCS อื่น ๆ เกือบทั้งหมด มันทำให้ Git พิจารณาใหม่เกือบทุกแง่มุมของการควบคุมเวอร์ชันที่ระบบอื่นส่วนใหญ่คัดลอกมาจากรุ่นก่อนหน้า สิ่งนี้ทำให้ Git เป็นเหมือนระบบไฟล์ขนาดเล็กมากขึ้นด้วยเครื่องมือที่ทรงพลังอย่างไม่น่าเชื่อที่สร้างขึ้นจากด้านบนแทนที่จะเป็น VCS


Jan Hudecเพิ่มความคิดเห็นที่สำคัญนี้:

แม้ว่ามันจะเป็นจริงและสำคัญในระดับแนวคิด แต่ก็ไม่เป็นความจริงในระดับที่เก็บข้อมูล
Git ไม่ใช้สันดอนสำหรับการจัดเก็บ
ไม่เพียงแค่นั้น แต่มันมีประสิทธิภาพมากกว่าในระบบอื่น ๆ เพราะมันไม่ได้เก็บประวัติต่อไฟล์เมื่อมันต้องการที่จะทำการบีบอัดเดลต้ามันใช้เวลาแต่ละหยดเลือกบาง blobs ที่มีแนวโน้มที่จะคล้ายกัน (ใช้การวิเคราะห์พฤติกรรมที่มีการประมาณที่ใกล้เคียงที่สุดของรุ่นก่อนหน้าและอื่น ๆ ) พยายามสร้าง deltas และเลือกที่เล็กที่สุด วิธีนี้สามารถ (มักจะขึ้นอยู่กับการวิเคราะห์พฤติกรรม) ใช้ประโยชน์จากไฟล์ที่คล้ายกันอื่น ๆ หรือรุ่นที่เก่ากว่าที่มีความคล้ายคลึงกว่าก่อนหน้านี้ พารามิเตอร์ "หน้าต่างแพ็ค" ช่วยให้ประสิทธิภาพการซื้อขายสำหรับคุณภาพการบีบอัดเดลต้า โดยทั่วไปค่าเริ่มต้น (10) ให้ผลลัพธ์ที่ดี แต่เมื่อพื้นที่มี จำกัด หรือเพื่อเพิ่มความเร็วในการถ่ายโอนเครือข่ายให้git gc --aggressiveใช้ค่า 250 ซึ่งทำให้มันทำงานช้ามาก แต่ให้การบีบอัดเพิ่มเติมสำหรับข้อมูลประวัติ


4
@JanHudec จุดดี ฉันได้รวมความคิดเห็นของคุณไว้ในคำตอบเพื่อให้มองเห็นได้ชัดเจนขึ้น
VonC

1
ไม่มีใครรู้คำวิทยาศาสตร์คอมพิวเตอร์สำหรับรูปแบบการจัดเก็บข้อมูลเหมือน Git หรือที่เก็บมูลค่าตามแฮช (หรืออะไรทำนองนั้น)
Joannes Vermorel

34
ในบริบทของคำถามที่แท้จริงของ OP ย่อหน้าแรกดูเหมือนจะทำให้เข้าใจผิดจริงๆ มันไม่ได้จนกว่าคุณจะไปถึงย่อหน้าสุดท้ายที่เราเรียนรู้ว่าใช่จริงแล้ว Git ทำ "เก็บ [... ] ความแตกต่างระหว่างไฟล์จริง ๆ แล้วหวังว่าข้อมูลนั้นถูกตั้งค่าไว้ด้านบนและไม่ฝังลึกดังนั้นกล่าวขอบคุณที่ อย่างน้อยก็รวมเรื่องจริงไว้ที่ไหนสักแห่งในคำตอบของคุณ;)
Josh O'Brien

1
@NickVolynkin เยี่ยมมาก! ฉันดีใจที่คำตอบเหล่านี้กำลังค้นหาผู้ชมจำนวนมากขึ้น
VonC

1
หนังสือที่ดีอีกเล่มหนึ่ง: Git From The Bottom Up: ftp.newartisans.com/pub/git.from.bottom.up.pdf
Jonas Berlin

46

Git เก็บแต่ละไฟล์อย่างมีเหตุผลภายใต้ SHA1 สิ่งนี้หมายความว่าถ้าคุณมีไฟล์สองไฟล์ที่มีเนื้อหาเดียวกันในที่เก็บ (หรือถ้าคุณเปลี่ยนชื่อไฟล์) จะมีการจัดเก็บสำเนาเพียงชุดเดียว

แต่นี่ก็หมายความว่าเมื่อคุณปรับเปลี่ยนส่วนเล็ก ๆ ของไฟล์และส่งมอบสำเนาของไฟล์จะถูกเก็บไว้ วิธีแก้ปัญหานี้ใช้ไฟล์แพ็ค นาน ๆ ครั้งไฟล์ "ที่หลวม" ทั้งหมด (อันที่จริงไม่ใช่แค่ไฟล์ แต่วัตถุที่มีคอมมิตและข้อมูลไดเรกทอรีด้วย) จาก repo จะถูกรวบรวมและบีบอัดลงในไฟล์แพ็ค ไฟล์บีบอัดถูกบีบอัดโดยใช้ zlib และไฟล์ที่คล้ายกันก็มีการบีบอัดเดลต้า

รูปแบบเดียวกันนี้ยังใช้เมื่อดึงหรือดัน (อย่างน้อยกับโพรโทคอลบางตัว) ดังนั้นไฟล์เหล่านั้นไม่จำเป็นต้องถูกบีบอัดอีกครั้ง

ผลลัพธ์ของสิ่งนี้คือที่เก็บ git ซึ่งประกอบด้วยสำเนาการทำงานที่ไม่มีการบีบอัดทั้งหมดไฟล์ล่าสุดที่ไม่มีการบีบอัดและไฟล์เก่าที่บีบอัดมักจะมีขนาดค่อนข้างเล็กและเล็กกว่าขนาดของสำเนาการทำงานสองเท่า และนี่หมายความว่ามันเล็กกว่า repo SVN ที่มีไฟล์เดียวกันแม้ว่า SVN จะไม่เก็บประวัติไว้ในเครื่อง


1
โอ้ Mercurial เป็นพื้นที่ที่มีประสิทธิภาพมากขึ้น
เบ็น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.