ความแตกต่างระหว่าง HEAD, แผนผังการทำงานและดัชนีใน Git คืออะไร?


488

มีคนบอกความแตกต่างระหว่าง HEAD, แผนผังการทำงานและดัชนีใน Git ได้ไหม?

จากสิ่งที่ฉันเข้าใจพวกเขาเป็นชื่อของสาขาที่แตกต่างกัน สมมติฐานของฉันถูกต้องหรือไม่


แก้ไข

ฉันพบสิ่งนี้

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

นี่หมายความว่า HEAD และแผนผังการทำงานเหมือนกันหรือไม่


26
ด้วยความเคารพต่อการแก้ไขของคุณ: ไม่อย่างแน่นอน HEADคือการกระทำที่ส่วนท้ายของสาขาปัจจุบัน หากคุณเพิ่งตรวจสอบสาขาคือไม่มีไฟล์ที่แก้ไขแล้วเนื้อหาจะตรงกับแผนผังการทำงาน ทันทีที่คุณแก้ไขอะไรมันจะไม่ตรงกันอีกต่อไป
Cascabel

6
ฉันคิดว่าคุณต้องอ่านสิ่งนี้: think-like-a-git.net
Andrzej Duś

5
ฉันจะเพิ่มStaging Areaในรายการนั้นด้วย คืออะไรHEAD, Working Tree, IndexและStaging Area
สีเขียว

2
ประโยคสุดท้ายของ @ Jefromi จะมีความชัดเจนมากขึ้นเป็น:> ทันทีที่คุณแก้ไขสิ่งใด ๆ ต้นไม้ทำงานไม่ตรงกับการมอบหมายของ HEAD อีกต่อไป
starscream_disco_party

3
สำหรับการอ่านใด ๆ ในอนาคตวิธีที่ดีที่สุดที่จะเข้าใจคำตอบบางอย่างเหล่านี้อย่างแท้จริงคือการเห็นและรู้สึกและมองเห็นภาพสิ่งที่เกิดขึ้น: นี่เป็นเครื่องมือที่ดีที่สุดสำหรับการเรียนรู้คอมไพล์: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

คำตอบ:


578

การอ้างอิงที่ดีอื่น ๆ อีกสองสามหัวข้อ:

ข้อความแสดงแทน

ผมใช้ดัชนีเป็นด่าน

เมื่อฉันกำลังจะทำการเปลี่ยนแปลงที่อาจไปผิดเพี้ยน - เมื่อฉันต้องการสำรวจทิศทางที่ฉันไม่แน่ใจว่าฉันสามารถติดตามผ่านหรือไม่ว่ามันเป็นความคิดที่ดีเช่นแนวคิดที่ต้องการ refactoring หรือเปลี่ยน ประเภทการแทน - ฉันตรวจสอบการทำงานของฉันลงในดัชนี หากนี่เป็นการเปลี่ยนแปลงครั้งแรกที่ฉันทำตั้งแต่การส่งครั้งล่าสุดฉันสามารถใช้ที่เก็บในเครื่องเป็นจุดตรวจสอบได้ แต่บ่อยครั้งที่ฉันมีการเปลี่ยนแปลงทางความคิดหนึ่งครั้งที่ฉันใช้เป็นชุดของขั้นตอนเล็กน้อย ฉันต้องการที่จะตรวจสอบหลังจากแต่ละขั้นตอน แต่บันทึกการกระทำจนกว่าฉันจะได้รับกลับไปทำงานรหัสการทดสอบ

หมายเหตุ:

  1. พื้นที่ทำงานเป็นต้นไม้ไดเรกทอรีของ (ต้นฉบับ) ไฟล์ที่คุณเห็นและแก้ไข

  2. ดัชนีเป็นเดี่ยวขนาดใหญ่ไฟล์ไบนารีใน<baseOfRepo>/.git/indexซึ่งจะแสดงรายการไฟล์ทั้งหมดในสาขาปัจจุบันของพวกเขาsha1 checksums แสตมป์เวลาและชื่อไฟล์ - มันไม่ไดเรกทอรีอื่นมีสำเนาของไฟล์ในนั้น

  3. ที่เก็บโลคัลเป็นไดเร็กทอรีที่ซ่อนอยู่ ( .git) รวมถึงobjectsไดเร็กทอรีที่มีทุกเวอร์ชันของทุกไฟล์ใน repo (local branch และสำเนาของ remote branch) เป็นไฟล์ "blob" ที่ถูกบีบอัด

อย่าคิดว่า 'ดิสก์' สี่อันที่แสดงในภาพด้านบนเป็นสำเนาแยกต่างหากของไฟล์ repo

ข้อความแสดงแทน

โดยทั่วไปแล้วพวกเขาจะมีชื่ออ้างอิงสำหรับ Git กระทำ การอ้างอิงมีสองประเภทหลัก: แท็กและส่วนหัว

  • แท็กเป็นการอ้างอิงถาวรที่ทำเครื่องหมายจุดเฉพาะในประวัติเช่น v2.6.29
  • ในทางตรงกันข้ามหัวจะถูกย้ายเสมอเพื่อสะท้อนตำแหน่งปัจจุบันของการพัฒนาโครงการ

ข้อความแสดงแทน

(หมายเหตุ: ตามที่ติโม Huovinen แสดงความคิดเห็นลูกศรเหล่านั้นไม่ใช่สิ่งที่มุ่งมั่นมันคือลำดับเวิร์กโฟลว์โดยทั่วไปแสดงลูกศรตามตำแหน่งที่กระทำครั้งแรกและสุดท้าย)1 -> 2 -> 3 -> 414

ตอนนี้เรารู้ว่าเกิดอะไรขึ้นในโครงการ
แต่หากต้องการทราบว่าเกิดอะไรขึ้นที่นี่ตอนนี้มีการอ้างอิงพิเศษที่เรียกว่า HEAD มันทำหน้าที่สองวัตถุประสงค์หลัก:

  • มันแจ้งให้ Git ทราบว่าจะใช้ไฟล์ใดเมื่อคุณชำระเงินและ
  • มันจะบอก Git ว่าจะใส่คอมมิชชันใหม่เมื่อใด

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

ข้อความแสดงแทน


20
หลายครั้งที่ฉันอ่านเกี่ยวกับคอมไพล์ฉันไม่เคยเข้าใจอย่างสมบูรณ์เลยฉันหงุดหงิดจริง ๆ และอยากใช้คำฉ; แต่ฉันอยู่ในชุมชน! คุณเคยพูดถึงหัว แต่ในภาพด้านบนมีหัวเดียวเสมอที่ส่วนหัวที่เหลืออยู่ **? "ปกติหัวชี้ไปที่หนึ่งในหัวดังนั้นทุกอย่างทำงานได้ดี" ฉันขอให้คุณอธิบายสิ่งนี้คำสั่ง Ur
Necktwi

12
@neckTwi HEAD เป็นคอมมิทชั่นปัจจุบันที่คุณใช้งานอยู่ ( stackoverflow.com/a/964927/6309 ) มันมักจะเป็นหนึ่งใน "หัวสาขา" (หนึ่งในความมุ่งมั่นอ้างอิงโดยสาขาแสดงถึงปลายของสาขาดังกล่าว) แต่คุณสามารถชำระเงิน (และทำงาน) กระทำใด ๆ หากคุณชำระเงินการยืนยันที่ไม่ใช่หัว (สาขา) คุณอยู่ในโหมด "ถอดหัว": stackoverflow.com/a/3965714/6309
VonC

1
@Imray ฉันเห็นด้วย แต่นั่นเป็นวิธีที่ฉันพบรูปภาพเหล่านั้นเมื่อ 5 ปีก่อน ( hades.name/blog/2010/01/28/… )
VonC

11
เกี่ยวกับดัชนีฉันคิดว่าสิ่งที่มีประโยชน์ที่สุดที่สามารถพูดได้คือ "ดัชนีนั้นเป็นอีกชื่อหนึ่งของพื้นที่จัดเตรียม" เช่น @ ashraf-alam กล่าว ฉันรู้สึกว่าเวลาพูดคุยกันส่วนใหญ่จะเรียกว่าพื้นที่จัดเตรียมซึ่งเป็นสาเหตุที่ฉันไม่ได้ทำการเชื่อมต่อโดยอัตโนมัติว่ามันเป็นสิ่งเดียวกันกับดัชนี
Pete

1
@ พีทฉันเห็นด้วย สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างระหว่างแคชและดัชนีให้ดูคำตอบอื่น ๆ ของฉันstackoverflow.com/a/6718135/6309
VonC

137

ความแตกต่างระหว่างHEAD (สาขาปัจจุบันหรือสถานะที่กำหนดล่าสุดในสาขาปัจจุบัน), ดัชนี (aka. การจัดเตรียมพื้นที่) และแผนผังการทำงาน (สถานะของไฟล์ในการชำระเงิน) อธิบายไว้ในส่วน"The Three States" ของ "1.3 Git Basics " บทของPro Gitหนังสือโดย Scott Chacon (ใบอนุญาตครีเอทีฟคอมมอนส์)

นี่คือภาพที่แสดงจากบทนี้:

การดำเนินงานในพื้นที่ - ไดเรกทอรีทำงานเทียบกับพื้นที่จัดเตรียม (ดัชนี) เทียบกับพื้นที่เก็บข้อมูล git (HEAD)

ในภาพด้านบน "ไดเร็กตอรี่ทำงาน" เหมือนกันกับ "แผนผังการทำงาน", "พื้นที่จัดเตรียม" เป็นชื่อสำรองสำหรับ git "index", และHEADจุดชี้ไปที่สาขาที่เช็คเอาท์ในปัจจุบันซึ่งเคล็ดลับชี้ไปที่การกระทำสุดท้ายใน " ไดเรกทอรี git (พื้นที่เก็บข้อมูล) "

โปรดทราบว่าgit commit -aขั้นตอนจะเปลี่ยนและกระทำในขั้นตอนเดียว


1
"ภาพที่มีค่าพันคำ". ขอบคุณ Jakub .. และขอบคุณสำหรับลิงค์
Joyce Babu

5
หมายเหตุ: working treeดูเหมือนจะเป็นที่ต้องการworking directoryในทุกวันนี้ ดูgithub.com/git/git/commit/…
VonC

3
รูปภาพนี้ไม่ถูกต้องเนื่องจาก Staging Area มีอยู่ในไฟล์เดียวชื่อ "index" - และไฟล์ดัชนีนั้นจะอยู่ในรูทของไดเรกทอรี. git ดังนั้นถ้าคุณกำหนด repo เป็นไดเรกทอรี. git พื้นที่จัดเตรียมนั้นจะอยู่ใน repo คอลัมน์ที่สามน่าจะมีป้ายกำกับว่า "Root Tree object" ที่ดีกว่าเพื่อระบุว่าไฟล์ที่เช็คเอาท์มาจากวัตถุที่กระทำและการกระทำที่เขียนต้นไม้ใหม่ไปยังวัตถุที่กระทำ
Jazimov

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

@Binarus: อันตรายในการทำซ้ำภาพขายส่งเช่นนี้มันทำหน้าที่ในการเผยแพร่ "การบิดเบือนความจริง" ที่ทำโดยผู้เขียน / หนังสือเล่มหนึ่ง ฉันคิดว่านี่เป็นกรณีของการตีความตามตัวอักษรกับการทำงานที่นี่: ในความหมายตามตัวอักษรดัชนีจริง ๆ แล้วมีอยู่ใน repo ถ้าคุณกำหนด repo เป็นทุกอย่างภายใต้โฟลเดอร์. git อย่างไรก็ตามในแง่ของการใช้งานดัชนีช่วยให้ Git รักษา DAG ในธุรกรรมซื้อคืนและสามารถคิดได้ว่าเป็นสิ่งภายนอก
Jazimov

64

แผนผังการทำงานของคุณคือสิ่งที่เป็นจริงในไฟล์ที่คุณกำลังทำงานอยู่

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

ดัชนีเป็นพื้นที่การแสดงละครที่ใหม่กระทำได้เตรียม โดยพื้นฐานแล้วเนื้อหาของดัชนีคือสิ่งที่จะเข้าสู่การส่งมอบใหม่ (แม้ว่าคุณจะทำเช่นgit commit -aนี้จะเป็นการเพิ่มการเปลี่ยนแปลงทั้งหมดในไฟล์ที่ Git รู้จักเกี่ยวกับดัชนีโดยอัตโนมัติก่อนที่จะกระทำดังนั้นมันจะยอมรับเนื้อหาปัจจุบันของแผนผังการทำงานของคุณ ) git addจะเพิ่มหรืออัปเดตไฟล์จากแผนผังการทำงานลงในดัชนีของคุณ


ขอบคุณมากสำหรับคำอธิบายที่ไบรอัน ดังนั้นแผนผังการทำงานมีการเปลี่ยนแปลงทั้งหมดที่ไม่มีข้อผูกมัด หากฉันยอมรับการเปลี่ยนแปลงของฉันด้วย git commit -a ดังนั้น ณ เวลาใดเวลาหนึ่งแผนภูมิการทำงานและดัชนีของฉันจะเหมือนเดิม เมื่อฉันกดไปที่ repo ส่วนกลางของฉันทั้งสามจะเหมือนกัน ฉันถูกไหม?
Joyce Babu

3
@ Vinod สวยมาก คุณสามารถมีไฟล์ในแผนผังการทำงานที่ Git ไม่รู้จักและไฟล์เหล่านั้นจะไม่ถูกผูกมัดด้วยgit commit -a(คุณต้องเพิ่มไฟล์ด้วยgit add) ดังนั้นแผนผังการทำงานของคุณอาจมีไฟล์พิเศษที่ดัชนีของคุณ repo ในพื้นที่ของคุณหรือ repo ระยะไกลของคุณไม่มี
Brian Campbell

2
@Vinod: แผนผังการทำงานและดัชนีสามารถกลายเป็นเหมือนเดิมได้โดยไม่ต้องคอมมิท (git เพิ่มการอัพเดตดัชนีจากแผนผังการทำงานและเช็คเอาต์ git <path> อัพเดตแผนผังการทำงานจากดัชนี) HEADหมายถึงการคอมมิชชันล่าสุดดังนั้นเมื่อคุณคอมมิชชันคุณกำลังอัพเดตHEADการคอมมิชชันใหม่ซึ่งตรงกับดัชนี การกดไม่มีส่วนเกี่ยวข้องกับมันมากนัก - มันทำให้สาขาในสาขาการแข่งขันระยะไกลใน repo ท้องถิ่นของคุณ
Cascabel

45

ต้นไม้ทำงาน

แผนผังการทำงานของคุณคือไฟล์ที่คุณกำลังทำงานอยู่

ดัชนี Git

  • git "index" คือที่ที่คุณวางไฟล์ที่คุณต้องการคอมมิทไปยังที่เก็บ git

  • ดัชนียังเป็นที่รู้จักกันแคช , แคชไดเรกทอรี , แคชไดเรกทอรีปัจจุบัน , พื้นที่การแสดงละคร , ไฟล์ฉาก

  • ก่อนที่คุณจะ "ยอมรับ" ไฟล์ (checkin) ไปยังที่เก็บ git คุณต้องวางไฟล์ในดัชนี git "index" ก่อน

  • ดัชนีไม่ใช่ไดเรกทอรีการทำงาน: คุณสามารถพิมพ์คำสั่งเช่นgit statusและ git จะบอกคุณว่าไฟล์ใดในไดเรกทอรีการทำงานของคุณถูกเพิ่มลงในดัชนี git (ตัวอย่างเช่นโดยใช้git add filenameคำสั่ง)

  • ดัชนีไม่ใช่ที่เก็บ git: ไฟล์ในดัชนี git คือไฟล์ที่ git จะส่งไปยังที่เก็บ git หากคุณใช้คำสั่ง git


1
โปรดทราบว่า Git 2.5 จะนำต้นไม้ทำงานหลายต้น ( stackoverflow.com/a/30185564/6309 ) +1
VonC

3
ฉันไม่แน่ใจว่า "ดัชนีไม่ใช่ไดเรกทอรีทำงาน" ถูกต้อง 100% ควรเป็น "ดัชนีไม่ใช่ไดเรกทอรีการทำงาน แต่รวมถึงไดเรกทอรีการทำงานทั้งหมด + การเปลี่ยนแปลงที่คุณต้องการยืนยันในครั้งต่อไป" หลักฐาน? ไปที่ที่เก็บ git reset --hard HEADเพื่อให้แน่ใจว่า index == แผนผังการทำงานของคุณ แล้ว: mkdir history && git checkout-index --prefix history/ -aผลที่ได้คือการทำซ้ำของต้นไม้การทำงานทั้งหมดของคุณในhistory/ไดเรกทอรีของคุณ Ergo git index> = ไดเรกทอรีการทำงาน git
Adam Kurkiewicz

3
ดัชนีไม่ใช่ไดเรกทอรีการทำงานและไม่จำเป็นต้องรวมไดเรกทอรีทำงาน ดัชนีเป็นเพียงไฟล์ภายในที่เก็บ git ที่เก็บข้อมูลสิ่งที่คุณต้องการส่ง
Boon

3
"ดัชนี" เก็บสแน็ปช็อตของเนื้อหาของแผนผังการทำงานและเป็นสแน็ปช็อตนี้ที่ใช้เป็นเนื้อหาของการส่งข้อมูลครั้งถัดไปดังนั้นหลังจากทำการเปลี่ยนแปลงใด ๆ กับไดเร็กทอรีการทำงานและก่อนที่จะรันคำสั่ง commit คุณ ต้องใช้คำสั่งเพิ่มเพื่อเพิ่มไฟล์ใหม่หรือไฟล์ที่แก้ไขใด ๆ ในดัชนี "( git-scm.com/docs/git-add )
anth

3
@ AdamKurkiewicz: การพิสูจน์ล้มเหลวหากคุณเป็นครั้งแรกecho untracked-data > untracked-fileก่อนหรือหลังgit reset --HARDและgit checkout-indexขั้นตอน คุณจะพบว่าผู้ที่ไม่ได้ติดตามไฟล์ที่ไม่ได้ไม่ได้อยู่ในhistoryไดเรกทอรี นอกจากนี้คุณยังสามารถปรับเปลี่ยนทั้งดัชนีและแผนผังต้นไม้ได้อย่างอิสระแม้ว่าการปรับเปลี่ยนดัชนีโดยไม่ต้องสัมผัสกับแผนผังต้นไม้นั้นเป็นเรื่องยาก (จำเป็นต้องใช้git update-index --index-info)
2560
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.