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


14

ฉันอ่านแล้วว่า Git ไม่ได้จัดเก็บไฟล์เดลต้า ถ้าเป็นจริงมันจะรองรับการย้อนกลับไฟล์เป็นเวอร์ชันก่อนหน้าได้อย่างไร หากมันจัดเก็บไฟล์ทั้งหมดพื้นที่เก็บข้อมูลบนดิสก์จะต้องมีขนาดใหญ่ขึ้นอย่างไม่สามารถจัดการได้ Git สนับสนุนการย้อนกลับไฟล์และส่งกลับไปยังไฟล์เวอร์ชัน 1 หรือไม่ มันสนับสนุนแนวคิดเกี่ยวกับเวอร์ชันของไฟล์หรือไม่? นี่คือ (ฉันเชื่อว่า) จำเป็นต่อการเข้าใจ VCS / DVCS และความต้องการของฉัน ฉันต้องสามารถเปรียบเทียบสิ่งที่ฉันกำลังจะเช็คอินกับรุ่นก่อนหน้า

คำตอบ:


44

Git ไม่ทิ้งข้อมูลด้วยตนเอง * ทุกเวอร์ชันก่อนหน้าของทุกไฟล์จะพร้อมใช้งานสำหรับการย้อนกลับส่วนต่างการตรวจสอบและอื่น ๆ

ทั้งต้นไม้เทียบกับไฟล์ส่วนบุคคล

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

# 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

ประโยชน์ของการวางแนวต้นไม้ส่วนใหญ่ความสามารถในการรับชมเป็นหน่วยของการเปลี่ยนแปลงที่พึ่งพาซึ่งกันและกันที่ทำกับส่วนต่าง ๆ ของต้นไม้ทั้งหมดโดยทั่วไปจะมีความสำคัญมากกว่าการพิมพ์พิเศษ (ซึ่งสามารถบรรเทาด้วยนามแฝงสคริปต์และอื่น ๆ ) ใช้เวลาขุดผ่านความมุ่งมั่นที่ผ่านมา

ประสิทธิภาพการจัดเก็บ

เมื่อวัตถุใหม่ (เช่นไฟล์ที่มีเนื้อหาที่มองไม่เห็นก่อนหน้านี้) เข้าสู่ระบบมันจะถูกเก็บไว้ด้วยการบีบอัดธรรมดา (zlib) เป็น "วัตถุหลวม" เมื่อมีวัตถุหลวมเพียงพอสะสม (ขึ้นอยู่กับgc.autoตัวเลือกการกำหนดค่าหรือเมื่อผู้ใช้รันgit gcหรือหนึ่งในคำสั่งการบรรจุระดับต่ำกว่า) Git จะรวบรวมวัตถุหลวมจำนวนมากไว้ใน "แพ็คไฟล์" เดียว

วัตถุในไฟล์แพ็คสามารถจัดเก็บได้ไม่ว่าจะเป็นข้อมูลที่ถูกบีบอัดแบบธรรมดา (เช่นเดียวกับวัตถุที่หลวมเพียงรวมกับวัตถุอื่น ๆ ) หรือบีบอัดเดลต้าต่อวัตถุอื่น ๆ Deltas สามารถถูกโยงเข้าด้วยกันเพื่อกำหนดความลึก ( pack.depth) และสามารถทำกับวัตถุที่เหมาะสมใด ๆ ( pack.windowควบคุมวิธีการที่ Git ค้นหาฐานเดลต้าที่ดีที่สุดอย่างกว้างขวาง Git รุ่นของไฟล์ที่ไม่เกี่ยวข้องในอดีตสามารถใช้เป็นฐานได้หากทำเช่นนั้น การบีบอัดเดลต้าที่ดี) ละติจูดที่การกำหนดค่าความลึกและขนาดหน้าต่างให้เอ็นจินการบีบอัดเดลต้ามักส่งผลให้การบีบอัดเดลต้าดีกว่าการบีบอัด“ diff” แบบง่าย ๆ แบบ CVS ในรูปแบบ CVS แบบง่าย ๆ

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

ดูที่Git เก็บวัตถุและส่วนPackfileของหนังสือ Git Communityได้อย่างไร นอกจากนี้ยังมีคอมไพล์แพ็ควัตถุ manpage

* คุณสามารถบอกได้ว่า Git ได้ทิ้งการกระทำโดย“ เขียนประวัติศาสตร์ใหม่” และด้วยคำสั่งเช่นการรีเซ็ต gitแต่แม้ในกรณีเหล่านี้ Git“ แฮงค์ลงบน” การกระทำที่ถูกทิ้งร้างใหม่ในขณะที่ในกรณีที่คุณตัดสินใจว่าคุณต้องการ ดูคอมไพล์ reflogและคอมไพล์ลูกพรุน


3
+1 ตามจำนวนและรายละเอียดของข้อมูลที่คุณให้
Tamara Wijsman

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

คริสคุณดูเหมือนจะมีความสามารถที่ดีในเรื่อง Git internals โอกาสใดที่คุณอาจจะแกว่งที่นี้หรือไม่? stackoverflow.com/questions/5176225/…
นาธานลอง

@ChrisJohnsen โปรดช่วยฉันเข้าใจสิ่งนี้ จากสิ่งที่คุณพูด Git จะได้ประสิทธิภาพการจัดเก็บที่คล้ายกัน (หรือดีกว่า) กว่าการโค่นล้ม ฉันรู้ว่าถ้าฉันส่งไฟล์ที่มีการเปลี่ยนแปลงเล็กน้อยหลายครั้งหลายคราข้อมูล 1GB สามารถบันทึกได้ใน 100MB Git สามารถทำเช่นเดียวกันได้หรือไม่?
Alireza Noori

@AlirezaNoori: ทุกอย่างขึ้นอยู่กับลักษณะของข้อมูลและการเปลี่ยนแปลงที่บันทึกไว้ (ขนาดของไฟล์ความสามารถในการบีบอัดของไฟล์ขนาดและตำแหน่งของการเปลี่ยนแปลง ฯลฯ ) บางสิ่งเช่นนี้ควรเป็นไปได้อย่างแน่นอน (ขึ้นอยู่กับข้อมูลเฉพาะ) โดยทั่วไปไฟล์แพ็คของ Git สามารถดึงมาจากฐานการบีบอัดเดลต้าที่มีขนาดใหญ่กว่าเมื่อเปรียบเทียบกับเดลต้าย้อนกลับตามลำดับเวลาที่เซิร์ฟเวอร์ SVN ใช้อย่างเคร่งครัด (ใช้หรือไม่ฉันไม่ปฏิบัติตามการพัฒนา SVN …) หากคุณมีคำถามเฉพาะบางข้อคุณควรพิจารณาถามคำถามใหม่ที่มีรายละเอียดที่เกี่ยวข้องทั้งหมด
Chris Johnsen

1

มันสามารถอ่านได้ในหน้าเดียวกัน:

...

ดังนั้น Git จะไม่บันทึกความสัมพันธ์การแก้ไขไฟล์อย่างชัดเจนในทุกระดับที่ต่ำกว่าแผนผังซอร์สโค้ด

...

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

...

ดังนั้นคุณสามารถกลับไปที่การแก้ไขก่อนหน้าของไฟล์และเปรียบเทียบสองไฟล์


1

ในความเป็นจริงแล้ว git ทำการบันทึกเดลตาของไฟล์ แต่มันจะบันทึกเป็นเดลต้าของทรีไฟล์ทั้งหมด

หากต้องการดูความแตกต่างระหว่างเวอร์ชันให้ทำหนึ่งอย่างต่อไปนี้:

  1. git diff - แสดงความแตกต่างระหว่างการตรวจสอบในรุ่นล่าสุดและไฟล์ที่มีการเปลี่ยนแปลง แต่ไม่ได้git addทำงานกับพวกเขา
  2. git diff --cached - แสดงความแตกต่างระหว่างเวอร์ชันก่อนหน้าและไฟล์ทั้งหมดที่เคยgit addใช้ แต่ยังไม่ได้ยืนยัน
  3. git diff commitid - แสดงความแตกต่างระหว่างไดเร็กตอรี่ทำงานปัจจุบันและคอมมิชชันก่อนหน้าตามที่ระบุไว้กับคอมมิท
  4. git diff commita..commitb - แสดงความแตกต่างระหว่างสองคอมมิท a และ b การกระทำอาจเป็นชื่อเชิงสัญลักษณ์เช่นกิ่งไม้หรือแท็ก

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