จะเปลี่ยนการกระทำในอดีตเพื่อรวมไฟล์ที่ไม่ได้รับได้อย่างไร


98

ฉันได้ทำการเปลี่ยนแปลงและลืมเพิ่มไฟล์ลงในชุดการเปลี่ยนแปลง หลังจากการกระทำอื่น ๆ ฉันตระหนักว่าขณะนี้ไฟล์หายไปจากการคอมHEAD^4มิต

ฉันจะเขียนคอมมิตก่อนหน้านี้ใหม่เพื่อรวมไฟล์ที่หายไปได้อย่างไร


คุณผลักดัน 4 ข้อตกลงนี้หรือไม่?
mvp

@mvp ไม่ใช่พวกเขาอยู่ในที่เก็บ git ในเครื่องของฉันเท่านั้น
kolrie

คำตอบ:


54

ใช้git rebase --interactive HEAD~4และตั้งค่าeditตัวเลือกสำหรับการกระทำที่คุณต้องการแก้ไข

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


ขอบคุณ. เป็นเช่นนั้นแม้ว่าฉันจะเป็นผู้ใช้ repo ระยะไกลเพียงคนเดียวหรือไม่? จะไม่ยอมให้ทำหรือgit push -fถ้าแน่ใจว่าต้นน้ำไม่เปลี่ยน?
kolrie

1
หากคุณเป็นผู้ใช้เพียงคนเดียวของ repo ระยะไกลคุณสามารถกดบังคับได้
Rafał Rawicki

7
ฉันคิดว่าคำแนะนำเหล่านี้ไม่ละเอียดเพียงพอ ในการลองครั้งแรกฉันได้รับแจ้งว่า "ไม่สามารถสร้างฐานใหม่ได้: ดัชนีของคุณมีการเปลี่ยนแปลงที่ไม่ได้ผูกมัด" ฉันมีแล้วaddแก้ไขไฟล์ที่หายไปแล้วดังนั้นฉันจึงทำการคอมมิตกับ "xxx" เป็นข้อความ จากนั้นฉันก็ใช้คำสั่ง rebase และเปลี่ยนการคอมมิต "xxx" จาก "pick" เป็น "edit" จากนั้นฉันก็ทำ "git rebase --continue" ตอนนี้เมื่อฉันดูประวัติฉันมี "xxx" เป็นคอมมิตล่าสุดและการคอมมิตก่อนหน้านี้ที่ฉันต้องการเพิ่มเข้าไปนั้นไม่เปลี่ยนแปลง ฉันสงสัยว่าฉันผิดพลาดตรงไหน?
Darren Cook

2
การบีบคอมมิตสุดท้ายจะไม่ทำให้ไฟล์อยู่ใน HEAD ~ 4
Justin

1
git เพิ่ม modifiedFiles; คอมมิตคอมมิต -m "Blah"; git rebase -i HEAD ~ 5; // เนื่องจากตอนนี้เพิ่มคอมมิตใหม่ดังนั้นเราจึงต้อง rebase ด้วย 5 แทน 4 ตอนนี้ย้ายคอมมิต "Blah" ไปที่บรรทัดที่สองแล้วเปลี่ยนจาก "Pick" เป็น "s" (squash) ซึ่งจะสควอชคอมมิตด้วย HEAD ~ 5 เป็นคำสั่งที่ดำเนินการจากบนลงล่าง
zstring

277

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

ในกรณีที่คุณยืนยันและรู้ตัวว่าลืมเพิ่มไฟล์ทันทีให้ทำดังนี้

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

ที่ไหน --no-editจะให้เหมือนกันกระทำข้อความ

peasy ง่าย!


22
นี่คือคำตอบ
Adam Bittlingmayer

5
ควรค่าแก่การกล่าวขวัญหากการกระทำไม่ได้ถูกผลักไปที่รีโมท
รามภัทรา

1
ใช่มันเป็นมูลค่าการกล่าวขวัญที่นี่ในการแสดงความคิดเห็น: มันสำหรับการใช้ก่อนที่จะผลักดัน ขอบคุณที่ชี้ให้เห็น
DrBeco

2
ข้อสังเกตประการหนึ่งคือการกระทำก่อนและหลัง--amendมีแฮชที่แตกต่างกัน
sonlexqt

6
ขอบคุณ แต่ก็ไม่สามารถที่: ศูนย์การค้า โอ.พี. HEAD^4ถามหา มันก็โอเคเหมือนเป็นภาคผนวกสำหรับการอ้างอิง ;)
DrBeco

11

หากคุณยังไม่ได้ผลักดันการกระทำ 4 ข้อนี้คุณสามารถทำได้ดังนี้:

สร้างไฟล์แพทช์สำหรับคอมมิตทั้งหมดเหล่านี้:

git format-patch -4

ย้อนกลับโดย 4 คอมมิต:

git reset --hard HEAD~4

เพิ่มไฟล์ที่หายไป:

git add missing-file

กระทำกับ--amend:

git commit --amend

ใช้โปรแกรมแก้ไขที่บันทึกไว้ทั้งหมดกลับ:

git am *.patch

หากคุณผลักดันคุณไม่ควรใช้วิธีนี้ แต่เพียงแค่ยอมรับข้อผิดพลาดของคุณและสร้างการกระทำอีกครั้งที่ด้านบนของ HEAD ซึ่งช่วยแก้ปัญหานี้ได้


หากคุณต้องการทำทีละขั้นตอนการเลือกเชอร์รี่หลังจากการแก้ไขจะง่ายกว่าการส่งออกเป็นแพตช์
Rafał Rawicki

1
นี่เป็นเรื่องของรสนิยม ฉันชอบgit format-patch/ git amดีกว่ามาก สิ่งสำคัญที่สุดคือช่วยให้คุณมั่นใจมากขึ้นหากคุณทำบางสิ่งบางอย่างผิดพลาดการกระทำที่บันทึกเป็นโปรแกรมแก้ไขในไฟล์ทางกายภาพถือเป็นเครือข่ายความปลอดภัยที่ดีที่สุดของคุณ
mvp

ความเชื่อมั่นที่แท้จริงคือในความเป็นจริงเมื่อใช้งานบนที่เก็บ git คุณจะไม่ลบอะไรเลย ความมุ่งมั่นเก่ามีให้จนกว่าคุณจะทำงานgit gc:)
Rafał Rawicki

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

2
คำแนะนำเหล่านี้ดูเหมือนจะยืดยาว แต่ค่อนข้างง่ายและปฏิบัติตามได้ง่าย ขอบคุณ. (ฉันต้องการเพียงแค่เพิ่มขั้นตอนสุดท้าย: rm *.patch)
คาร์เรนคุก

9

แม้ว่าคำตอบที่ยอมรับจะถูกต้อง แต่ก็ไม่มีคำแนะนำโดยละเอียดเกี่ยวกับวิธีดำเนินการแก้ไขคอมมิตในระหว่างกระบวนการ rebase

  • ขั้นแรกเริ่มกระบวนการ rebase:

    git rebase --interactive HEAD~4
    
  • รายการกระทำจะนำเสนอให้เลือกกระทำคุณต้องการที่จะแก้ไขโดยการเปลี่ยนคำpickไปeditและบันทึกไฟล์

  • ทำการแก้ไขที่จำเป็นในโค้ดของคุณ (อย่าลืมเรียกใช้git addไฟล์ใหม่)

  • หลังจากการแก้ไขทั้งหมดเสร็จสิ้นปัญหาgit commit --amend- สิ่งนี้จะแก้ไขการกระทำที่ทำเครื่องหมายเป็นedit

  • เรียกใช้git rebase --continueซึ่งจะเสร็จสิ้นกระบวนการ (หากมีการทำเครื่องหมายว่าเป็นจำนวนeditมากกว่าขั้นตอนข้างต้นจะต้องทำซ้ำ)

หมายเหตุสำคัญ:

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

  • GIT บังคับให้คุณทำstashก่อนทำการรีเบตใหม่หากไดเร็กทอรีการทำงานของคุณไม่สะอาด อย่างไรก็ตามคุณสามารถgit stash pop / git stash applyในระหว่างการ rebase เพื่อแก้ไขการเปลี่ยนแปลงเหล่านี้ (เช่นการเปลี่ยนแปลงที่ซ่อนไว้ก่อนเริ่มกระบวนการ rebase) เป็นคอมมิตที่ทำเครื่องหมายเป็นedit

  • หากมีบางอย่างผิดพลาดและคุณต้องการเปลี่ยนกลับการเปลี่ยนแปลงที่เกิดขึ้นในระหว่างกระบวนการ rebase ก่อนที่จะเสร็จสิ้น (เช่นคุณต้องการย้อนกลับไปที่จุดก่อนที่จะเริ่ม rebase) ให้ใช้git rebase --abort- อ่านเพิ่มเติม: วิธีการยกเลิกฐานข้อมูลแบบโต้ตอบถ้า --abort doesn ' t ทำงาน?

  • ดังที่กล่าวไว้ในคำตอบที่ยอมรับ:

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

    คำตอบว่าทำไมอยู่ในGit Book (ย่อหน้าที่ชื่อว่า " The Perils of Rebasing "):

    อย่า rebase คอมมิตที่มีอยู่นอกที่เก็บของคุณ

    หากคุณปฏิบัติตามแนวทางนั้นคุณจะสบายดี ถ้าคุณไม่ทำคนอื่นจะเกลียดคุณและคุณจะถูกเพื่อนและครอบครัวดูถูก

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

    [... ]

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