ตรวจสอบการกระทำเก่าและการดูแลหัวหน้าในสาขาหลักหรือไม่?


85

ขณะนี้สำหรับการเปลี่ยนไปใช้คอมมิตคอมไพล์อื่น (ในสาขาเดียวกัน ... จริงๆแล้วในสาขาหลัก!) ฉันกำลังดำเนินการคำสั่ง

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

ตอนนี้ทุกครั้งที่ฉันทำคอมไพล์นี้บอกฉันว่าตอนนี้ฉันหัวแตก ฉันจะไปที่การกระทำที่เก่ากว่าและยังคงรักษาหัวหน้าในสาขาเดียวกันได้อย่างไร


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

จากสิ่งที่ฉันเข้าใจจากข้อความของ git มันไม่ได้ชี้ไปที่ใดเลยซึ่งเป็นสิ่งที่ไม่พึงปรารถนา
กินเอลิเซียม

1
ข้อความ Git จะแสดงเมื่อคุณตรวจสอบการคอมมิตเฉพาะเช่นที่ระบุว่า "HEAD is now at ea3d5ed ... " ซึ่งจะบอกให้คุณทราบว่า HEAD กำลังชี้ไปที่ใดที่หนึ่ง เป็นเพียงการชี้ตำแหน่งที่ไม่มีชื่ออื่นยกเว้น HEAD (ในขณะนี้เนื่องจาก a git checkoutไปยังชื่ออื่นหรือชื่อสาขาจะย้าย HEAD ไปยังที่ใหม่นั้น)
Greg Hewgill

คำตอบที่ให้ไว้อธิบายเรื่องนี้อย่างเพียงพอหรือมีอะไรที่เราสามารถอธิบายได้ชัดเจนกว่านี้? เรายินดีที่จะชี้แจงคำตอบให้กับคุณหากไม่ได้ตอบคำถามของคุณ
Brian Campbell

หากคุณมาที่นี่เพื่อหาวิธีตรวจสอบการคอมมิตอื่นในขณะที่ทำให้ HEAD ไม่เปลี่ยนแปลงอย่างสมบูรณ์ (เช่นเพื่อเปลี่ยนกลับไปใช้คอมมิตเก่า): git revert --no-commit 0766c053..HEADจะทำสิ่งนี้คอม0766c053มิตที่คุณต้องการเช็คเอาต์อยู่ที่ไหน นี้เป็นจากstackoverflow.com/a/21718540/525872
Jo Liss

คำตอบ:


193

ส่วนใหญ่เมื่อฉันทำสิ่งนี้ฉันจะชำระเงินไปที่สาขาชั่วคราว:

git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

หลังจากทำเสร็จฉันก็ลบสาขา


79

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

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

git checkout -b newbranch ea3d5ed

เพื่อช่วยให้เห็นภาพนี่คือแผนภาพบางส่วนที่แสดงให้เห็นว่าการทำงานบนหัวแยกแตกต่างจากการทำงานในสาขา

เริ่มต้นด้วย 3 commits บนmasterA, B และ C masterคือสาขาปัจจุบันดังนั้นHEADชี้ไปmasterที่ซึ่งชี้ให้ยอมรับ C

ABC
* - * - * <- หลัก <- HEAD

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

เอบีซีดี
* - * - * - * <- หลัก <- HEAD

ตอนนี้ให้ตรวจสอบการออก B HEADให้เราแฝด

เอบีซีดี
* - * - * - * <- มาสเตอร์
   ^
    \-- ศีรษะ

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

เอบีซีดี
* - * - * - * <- มาสเตอร์
    \
     * <- หัว
     จ

หากเราตัดสินใจเช็คเอาต์masterอีกครั้งในภายหลังจะไม่มีสิ่งใดอ้างถึง E

เอบีซีดี
* - * - * - * <- หลัก <- HEAD
    \
     *
     จ

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

ดังนั้นแทนที่จะตรวจสอบการแก้ไขที่เปลือยเปล่าและถอดหัวออกหากคุณรู้สึกว่ากำลังจะทำอะไรมากขึ้นคุณควรใช้git checkout -b branch Bเพื่อสร้างสาขาและตรวจสอบ ตอนนี้ความมุ่งมั่นของคุณจะไม่สูญหายเนื่องจากจะรวมอยู่ในสาขาที่คุณสามารถอ้างถึงได้อย่างง่ายดายและรวมในภายหลัง

เอบีซีดี
* - * - * - * <- มาสเตอร์
   ^
    \ - สาขา <- HEAD

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


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

5
@devoured elysium "detached head" หมายความว่าคุณมีHEADref ที่ชี้ไปที่ SHA-1 ของคอมมิตโดยตรงแทนที่จะชี้ไปที่สาขาซึ่งจะชี้ไปที่การกระทำ เนื่องจากหัวหน้าของคุณไม่ได้อ้างอิงสาขา Git จึงไม่รู้ว่าจะอัปเดตสาขาใดเมื่อคุณเพิ่มคอมมิตใหม่ ดังที่ฉันได้อธิบายไว้ในตอนต้นของคำตอบของฉันมันเป็นเรื่องดีอย่างยิ่งที่จะมีหัวแยกหากคุณจะกลับไปใช้เวอร์ชันเก่าเพื่อสร้างหรือทดสอบโค้ด คุณสามารถกลับไปที่สาขาได้ตลอดเวลาด้วยgit checkout masterหรือสิ่งที่คล้ายกัน เป็นเพียงปัญหาหากคุณกระทำในขณะที่คุณมีหัวแยก
Brian Campbell

@BrianCampbell - หลังจากสร้างกิ่งก้าน (ที่หัวของคุณอยู่) แล้วคุณจะรวมสาขาเป็น B และรวม B เป็นหลัก คุณควรทำอย่างไรต่อไป?
amey1908

คำอธิบายของคุณทำให้ฉัน 'คลิก' สิ่งอื่น ๆ อีกมากมาย ขอขอบคุณ. ในที่สุดฉันก็อาจจะเข้าใจคอมไพล์แล้ว ...
โจ

8

หากคุณต้องการกลับไปเล่นคอมมิตก่อนหน้านี้โดยไม่ทำการเปลี่ยนแปลงใด ๆ คุณสามารถทำได้

git co <previous-commit-id>

คุณจะอยู่ในสาขาที่เรียกว่า "(ไม่มีสาขา)" หลังจากคำสั่งนี้

ยืนยันโดย

git br

หลังจากที่คุณเล่นด้วยรหัสที่ผูกมัดก่อนหน้านี้คุณสามารถเปลี่ยนไปใช้สาขาที่คุณเคยอยู่ได้

git co <the-branch-you-were-on>

"(ไม่มีสาขา)" จะถูกลบโดยอัตโนมัติ วิธีนี้คุณไม่จำเป็นต้องสร้างสาขาชั่วคราว


5

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

นั่นคือคำอธิบายสั้น ๆ คำฟุ่มเฟือยด้านล่างหวังว่าจะช่วยในการทำความเข้าใจว่า HEAD และ Master แตกต่างกันอย่างไร:

โดยปกติสิ่งต่างๆจะมีลักษณะดังนี้:

C ← refs/heads/master ← HEAD 
↓
B
↓
A

ซึ่งจะบอกว่า:“ พาเรนต์ของ C คือ B และพาเรนต์ของ B คือ A สาขาที่ชี้ไปที่ C และฉันได้ตรวจสอบเนื้อหาของมาสเตอร์แล้ว นอกจากนี้เมื่อฉันยอมรับมาสเตอร์จะได้รับการอัปเดต”

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

ดังนั้นหากคุณต้องการตรวจสอบคอมมิตเก่าต้องอัปเดต HEAD ให้ชี้ไปที่คอมมิตที่ต้องการ git-checkoutทำแค่นั้น:

C ← refs/heads/master 
↓
B ← HEAD
↓
A

ตอนนี้คุณทิ้งสาขาไว้ข้างหลังเพราะคุณกำลังมองหาสิ่งเก่า ๆ ไม่เป็นไรอย่างที่คำแนะนำ "หัวแยก" บอกคุณอย่างใจเย็น (เน้นของฉัน):

คุณสามารถมองไปรอบ ๆ ทำการเปลี่ยนแปลงทดลองและยืนยันและคุณสามารถละทิ้งการกระทำใด ๆ ที่คุณทำในสถานะนี้โดยไม่ส่งผลกระทบต่อสาขาใด ๆโดยดำเนินการชำระเงินอีกครั้ง

ในทางกลับกันในขณะที่การรีเซ็ตสาขาของคุณจะได้รับ HEAD ในที่ที่ต้องการมันจะมีผลที่แตกต่างกันมาก

C
↓
B ← refs/heads/master ← HEAD
↓
A

การกระทำ C จะกลายเป็นขยะเนื่องจากคุณได้ประกาศว่าคุณไม่ต้องการให้เป็นส่วนหนึ่งของสาขาหลักอีกต่อไป

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

(บางทีอาจจะดูใน GitHub, gitk หรือ gitweb เพื่อเรียกดูประวัติการกระทำหากการตกราง HEAD ของคุณยังคงทำให้คุณรำคาญ)


1

คำถามค่อนข้างคลุมเครือ แต่ถ้าคุณต้องการเพียงแค่เปลี่ยนไฟล์ในโครงสร้างการทำงานของคุณคุณสามารถทำได้:

git checkout [commit|branch] -- .

จากนั้นคุณสามารถจัดขั้นตอนการเปลี่ยนแปลงและสร้างคอมมิตใหม่ได้หากต้องการ สิ่งนี้มีประโยชน์ในบางครั้ง


0

ฉันคิดว่าฉันเข้าใจคำถามของคุณ นี่คือสิ่งที่ฉันพบเพื่อแก้ปัญหานี้ และไม่มีโซลูชัน GUI คุณสามารถใช้คำสั่งเพื่อแก้ปัญหาได้เท่านั้นและมันง่ายมาก

ขั้นตอนที่ 1: สร้างแท็กของคอมมิตเก่าที่คุณต้องการย้อนกลับ

เช่นแท็ก v2.0

ขั้นตอนที่ 2: git checkout v2.0

นี่คือตอนนี้ HEAD ของคุณชี้ไปที่คอมมิต 'v2.0' แต่มาสเตอร์ยังคงชี้ไปที่คอมมิตสุดท้าย

C:\Program Files\Git\doc\git\html\git-checkout.html เอกสารนี้อาจช่วยคุณได้

หรือพิมพ์ git help <checkout>

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