การเปลี่ยนคอมมิทข้อความหลังจากกด (เนื่องจากไม่มีใครดึงมาจากระยะไกล)


981

ฉันได้ทำคอมไพล์และผลักดันในภายหลัง ฉันต้องการเปลี่ยนข้อความยืนยัน ถ้าฉันเข้าใจถูกต้องนี่ไม่แนะนำให้เลือกเพราะบางคนอาจดึงจากที่เก็บระยะไกลก่อนที่ฉันจะทำการเปลี่ยนแปลงดังกล่าว ถ้าฉันรู้ว่าไม่มีใครดึง?

มีวิธีทำเช่นนี้หรือไม่?


คุณลองทำอะไร สมมติว่าคุณรู้วิธีเปลี่ยนข้อความยืนยันแล้วลองและผลักดัน Git จะบอกคุณว่าคุณต้องทำอะไรเพื่อให้มันเกิดขึ้น
Andrew Marshall

1
ดูคำตอบสำหรับคำถาม "ฉันจะแก้ไขข้อความคอมมิทที่ไม่ถูกต้องเป็นคอมไพล์ได้อย่างไร?" stackoverflow.com/a/457396/444639
Mike Rylander

4
ประกาศ - คำถามเกี่ยวกับคอมไพล์ของ Google ก่อให้เกิดอันดับ 1!
Manish Shrivastava


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

คำตอบ:


1372

การเปลี่ยนประวัติศาสตร์

หากเป็นการกระทำล่าสุดคุณสามารถทำสิ่งนี้ได้:

git commit --amend

สิ่งนี้จะนำตัวแก้ไขพร้อมข้อความยืนยันล่าสุดและช่วยให้คุณแก้ไขข้อความได้ (คุณสามารถใช้-mหากคุณต้องการลบข้อความเก่าและใช้ข้อความใหม่)

ใจเร่งเร้า

จากนั้นเมื่อคุณกดให้ทำสิ่งนี้:

git push --force-with-lease <repository> <branch>

หรือคุณสามารถใช้ "+":

git push <repository> +<branch>

หรือคุณสามารถใช้--force:

git push --force <repository> <branch>

ระวังเมื่อใช้คำสั่งเหล่านี้

  • หากมีคนอื่นผลักดันการเปลี่ยนแปลงในสาขาเดียวกันคุณอาจต้องการหลีกเลี่ยงการทำลายการเปลี่ยนแปลงเหล่านั้น --force-with-leaseตัวเลือกที่เป็นที่ปลอดภัยที่สุดเพราะมันจะยกเลิกหากมีการเปลี่ยนแปลงใด ๆ ต้นน้ำ (

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

การดึง / ดึงข้อมูลในภายหลัง

ทุกคนที่ดึงแล้วจะได้รับข้อความแสดงข้อผิดพลาดและพวกเขาจะต้องอัปเดต (สมมติว่าพวกเขาไม่ได้ทำการเปลี่ยนแปลงด้วยตนเอง) โดยทำสิ่งนี้:

git fetch origin
git reset --hard origin/master # Loses local commits

reset --hardระมัดระวังในการใช้ หากคุณมีการเปลี่ยนแปลงสาขาการเปลี่ยนแปลงเหล่านั้นจะถูกทำลาย

หมายเหตุเกี่ยวกับการแก้ไขประวัติ

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

ถ้าคุณไม่คิดว่าคุณกำลังทำลายข้อมูลแล้วอยู่ห่างจาก--force... สิ่งเลวร้ายที่อาจจะเกิดขึ้น

นี่คือเหตุผลที่--force-with-leaseค่อนข้างปลอดภัย


13
ระวังด้วย "แก้ไข" ราวกับว่าพวกเขามีในท้องถิ่นใด ๆ ที่ไม่ได้ทำสัญญาไว้พวกเขาจะ "หลงทาง" ( หายไปจริงๆหมายถึงเด็กกำพร้าแต่การกู้คืนพวกเขาไม่ชัดเจน)
Andrew Marshall

1
คุณอาจต้องการระบุชื่อสาขาเมื่อคุณกด --force มิฉะนั้นคุณอาจกดมากกว่าที่คุณคาดไว้
user693960

1
@ user693960: Git จะส่งเฉพาะสิ่งที่คุณกำหนดค่าให้กดเท่านั้น
Dietrich Epp

10
เพียงแค่git push --forceไม่มี <repository> และตัวเลือก <branch> ก็ใช้งานได้เช่นกันหากคุณตั้งค่าอัปสตรีม
ahnbizcad

2
คุณสามารถยกตัวอย่างของ<repository>? มันคือoriginอะไร org/repo? หรือเพียงแค่repo?
MikeSchinkel

440

เพียงแค่พูดว่า :

git commit --amend -m "New commit message"

แล้ว

git push --force

8
ในกรณีของฉันgit push origin <BRANCH-NAME>ไม่ทำงานฉันต้องใช้git push --forceตามที่อธิบายในคำตอบที่ยอมรับ
Gabriel

1
มันไม่ได้ผลสำหรับฉัน ต้องให้เราgit push --forceไม่เช่นนั้นแรงผลักดันจะไม่ผ่าน
ahnbizcad

4
@ hahnbizcad มันควรจะทำงาน เพียงตรวจสอบให้แน่ใจว่าชื่อสาขาถูกต้อง
วิลเลียม

3
ฉันเชียร์ความเรียบง่ายในคำอธิบายของคุณ! ฉันใช้มันบ่อยกว่า
Vasikos

3
ฉันใช้คำสั่งเหล่านี้สำเร็จหลังจาก "เลิกป้องกัน" สาขาของฉันชั่วคราวซึ่งเกิดขึ้นในโครงการที่โฮสต์โดย GitLab ของฉัน ถ้าคุณมีปัญหานี้ก่อนที่จะใช้คำสั่งเหล่านี้โปรดดูที่นี้stackoverflow.com/a/32267118/1423345จะ "เลิกป้องกัน" สาขาและคุณสามารถ "ปกป้อง" อีกครั้งหลังจากที่ทำแก้ไขข้อความกระทำ :)
จอห์น

261

หากต้องการแก้ไขการมอบหมายอื่นนอกเหนือจากล่าสุด:

ขั้นตอนที่ 1 : git rebase -i HEAD~nทำการ rebase เชิงโต้ตอบสำหรับการnกระทำครั้งสุดท้ายที่ได้รับผลกระทบ (เช่นถ้าคุณต้องการเปลี่ยนข้อความคอมมิท 3 กระทำย้อนกลับให้ทำgit rebase -i HEAD~3)

git จะปรากฏตัวแก้ไขขึ้นเพื่อจัดการคอมมิทเหล่านั้นให้สังเกตคำสั่งนี้:

#  r, reword = use commit, but edit the commit message

นั่นคือสิ่งที่เราต้องการ!

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

โปรดทราบว่าหากคุณแก้ไข 'แผน' การรีบูต แต่ยังไม่ได้เริ่มต้นกระบวนการให้คุณเปลี่ยนชื่อไฟล์ให้เรียกใช้:

git rebase --continue

หากคุณต้องการเปลี่ยนเท็กซ์เอดิเตอร์ที่ใช้สำหรับเซสชันแบบโต้ตอบ (เช่นจากค่าดีฟอลต์ vi เป็นนาโน) ให้รัน:

GIT_EDITOR=nano git rebase -i HEAD~n

ขั้นที่ 3 : Git จะปรากฏตัวแก้ไขอีกตัวสำหรับการแก้ไขทุกครั้งที่คุณวางไว้rก่อนหน้า อัปเดตการส่งข้อความตามที่คุณต้องการจากนั้นบันทึกและปิดตัวแก้ไข

ขั้นตอนที่ 4 : หลังจากที่ยอมรับข้อความทั้งหมดจะถูกอัปเดต คุณอาจต้องการทำgit push -fเพื่ออัพเดตรีโมต


21
คำตอบนี้ควรได้รับการยอมรับเนื่องจากมีความเป็นไปได้ที่จะเปลี่ยนการกระทำอื่นนอกเหนือจากการกระทำล่าสุดซึ่งแตกต่างจากคำตอบที่ยอมรับ คุณบันทึกวันของฉัน ขอบคุณ!
xZero

1
เลือก n = 3 สำหรับ 3 การกระทำล่าสุด:git rebase -i HEAD~3
HeikoS

ถ้าคุณแก้ไข rebase ของคุณ 'แผน' git rebase --continueยังไม่ได้เริ่มต้นกระบวนการของการปล่อยให้คุณเปลี่ยนชื่อไฟล์ที่วิ่ง และถ้าคุณต้องการที่จะเปลี่ยนแปลงแก้ไขข้อความที่ใช้สำหรับเซสชั่นแบบโต้ตอบ (เช่นจากค่าเริ่มต้นviไปnano) GIT_EDITOR=nano git rebase -i HEAD~nวิ่ง
Jamie Birch

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

ฉันได้ทำการแก้ไขที่แนะนำเพื่อใส่ความคิดเห็นที่มีประโยชน์จาก @JamieBirch ลงในคำตอบอาจต้องการตรวจสอบ
Notts90 รองรับโมนิกา

44

ใช้สองขั้นตอนเหล่านี้ในคอนโซล:

git commit --amend -m "new commit message"

แล้ว

git push -f

เสร็จแล้ว :)


ขอบคุณ, นั่นเป็นขั้นตอนสำหรับแก้ไขความคิดเห็นล่าสุดเท่านั้นหรือสามารถใช้สำหรับความคิดเห็นที่เก่ากว่าด้วยได้หรือไม่?
Jay

@Jay ขออภัยสำหรับการตอบกลับล่าช้าขั้นตอนเหล่านี้เฉพาะสำหรับการแก้ไขข้อความยืนยันล่าสุด
Abdul Rizwan

19

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

โปรดทราบว่า - บังคับใช้กับการอ้างอิงทั้งหมดที่ถูกผลักดังนั้นจึงใช้กับ push.default ที่ตั้งค่าให้ตรงกันหรือกับปลายทางการพุชที่กำหนดค่าด้วยรีโมต *. push อาจเขียนทับ refs นอกเหนือจากสาขาปัจจุบัน (รวมถึง refs ท้องถิ่นที่ อย่างเคร่งครัดหลังคู่ที่ห่างไกลของพวกเขา) หากต้องการบังคับให้กดไปที่สาขาเดียวให้ใช้ + ด้านหน้าของ refspec เพื่อดัน (เช่น git push Origin + master เพื่อบังคับให้กดไปที่สาขาหลัก)


3
หมายเหตุสำคัญมาก
peterh - Reinstate Monica

ไม่มีคำตอบแรงใดที่เหมาะกับฉันเพราะฉันไม่มีสิทธิ์ของ ForcePush บนเซิร์ฟเวอร์ แต่ฉันต้องการทำการคอมมิชชันซึ่งเปลี่ยนข้อความการส่งก่อนหน้า ฉันสามารถเขียน "ส่งข้อความการเปลี่ยนแปลง" ไปยังส่วนความคิดเห็นของการกระทำนั้น
nurettin

11

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



8
git commit --amend

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

git push --force-with-lease

2

อีกตัวเลือกหนึ่งคือการสร้าง "errata commit" เพิ่มเติม (และพุช) ซึ่งอ้างอิงถึงวัตถุกระทำที่มีข้อผิดพลาด - errata กระทำใหม่ยังให้การแก้ไข errata commit เป็นการกระทำที่ไม่มีการเปลี่ยนแปลงรหัสที่สำคัญ แต่เป็นข้อความยืนยันที่สำคัญตัวอย่างเช่นเพิ่มอักขระเว้นวรรคหนึ่งตัวไปยังไฟล์ readme ของคุณและส่งการเปลี่ยนแปลงนั้นด้วยข้อความยืนยันที่สำคัญหรือใช้ตัวเลือก git--allow-emptyของคุณและกระทำการเปลี่ยนแปลงว่ามีการกระทำที่สำคัญข้อความหรือใช้ตัวเลือกคอมไพล์ แน่นอนว่าง่ายกว่าและปลอดภัยกว่าการรีบูตมันไม่ได้แก้ไขประวัติจริงและทำให้ต้นไม้สาขาสะอาด (ใช้amendเป็นตัวเลือกที่ดีถ้าคุณแก้ไขการคอมมิชชันล่าสุด แต่การคอมมิชชันแบบ errata อาจเป็นทางเลือกที่ดีสำหรับการคอมมิทรุ่นเก่า) ประเภทของสิ่งนี้เกิดขึ้นน้อยมากที่การบันทึกความผิดพลาดนั้นดีพอ ในอนาคตหากคุณต้องการค้นหาผ่านบันทึกการใช้คอมไพล์สำหรับคำหลักคุณลักษณะการกระทำดั้งเดิม (ผิดพลาด) อาจไม่ปรากฏเนื่องจากมีการใช้คำหลักผิดในการส่งต้นฉบับ (พิมพ์ต้นฉบับ) - อย่างไรก็ตามคำหลักจะปรากฏขึ้น ใน errata commit ซึ่งจะนำคุณไปยังการคอมมิทดั้งเดิมที่มีการพิมพ์ผิด นี่คือตัวอย่าง:

บันทึก $ git
กระทำ 0c28141c68adae276840f17ccd4766542c33cf1d
ผู้เขียน: ครั้งแรกที่ผ่านมา 
วันที่: พุธ 8 สิงหาคม 15:55:52 2018 -0600

    ข้อผิดพลาด Errata:
    การกระทำนี้ไม่มีการเปลี่ยนแปลงรหัสที่สำคัญ
    การส่งนี้จัดทำขึ้นเพื่อบันทึกการแก้ไขข้อความการส่งก่อนหน้าเท่านั้น
    ที่เกี่ยวข้องกับการกระทำวัตถุ e083a7abd8deb5776cb304fa13731a4182a24be1
    ข้อความคอมมิชชันเดิมไม่ถูกต้อง:
        เปลี่ยนสีพื้นหลังเป็นสีแดง
    การแก้ไข (* เน้นการเปลี่ยนแปลง *):
        เปลี่ยนสีพื้นหลังเป็น * blue *

ส่งมอบ 032d0ff0601bff79bdef3c6f0a02ebfa061c4ad4
ผู้เขียน: ครั้งแรกที่ผ่านมา 
วันที่: พุธ 8 สิงหาคม 15:43:16 2018 -0600

    ข้อความการส่งระหว่างกาลบางข้อความ

ส่ง e083a7abd8deb5776cb304fa13731a4182a24be1
ผู้เขียน: ครั้งแรกที่ผ่านมา 
วันที่: พุธ 8 สิงหาคม 13:31:32 2018 -0600

    เปลี่ยนสีพื้นหลังเป็นสีแดง

ปล้นนี้ดูมีแนวโน้ม คุณสามารถแสดงคำสั่งที่จำเป็นในการทำ "errata commit" เฉพาะโพสต์นี้แสดงขึ้นใน google ตามข้อกำหนดเหล่านี้
จิม

1
“ การกระทำที่ผิดพลาด” เป็นเพียงการกระทำปกติด้วยข้อความที่อ้างอิงถึงการกระทำที่ผิดพลาดก่อนหน้านี้การจัดทำเอกสารและการแก้ไขข้อผิดพลาดก่อนหน้า git commit -m “fixed feature A”(สมมติว่าคอมไพล์ให้รหัสกระทำนี้เป็น e3ab7312 ... ... (ต่อมาคุณทราบว่าข้อความของคุณไม่ถูกต้องดังนั้นตอนนี้จึงทำการเปลี่ยนแปลงที่ไม่สำคัญกับไฟล์เช่นการเพิ่มช่องว่างในไฟล์ readme หรือใช้—allow-emptyตัวเลือก git) .. git commit -m “Errata commit for previous commit e3ab7312... original message should have been ‘fixed feature *B*’'' '
rob_7cc

1
... หากคุณต้องการค้นหาบันทึก git ในภายหลังเพื่ออ้างถึง "คุณสมบัติ B" การส่งข้อมูล errata จะปรากฏขึ้น แต่ข้อความการส่งข้อมูล errata มีการอ้างอิงไปยัง ID การส่งต้นฉบับซึ่งให้การตรวจสอบย้อนกลับแบบเต็ม BTW คำว่า "errata กระทำ" ไม่มีอะไรพิเศษ (ไม่มีคำสั่ง "errata" หรือตัวเลือกในคอมไพล์) ... มันเป็นเพียงคำศัพท์ของฉันสำหรับการกระทำปกติที่ให้การแก้ไขการกระทำก่อนหน้านี้ที่มีข้อผิดพลาด / พิมพ์ผิด
rob_7cc

ปล้นนั่นใช้งานได้ดีมาก ฉันสามารถเพิ่มการมอบหมายที่ว่างเปล่าใหม่พร้อมคำอธิบายที่ถูกต้องซึ่งชี้ไปที่การส่งต้นฉบับโดยใช้ SHA ตอนนี้ทั้งคู่แสดงใน 'git chain' ของฉันสำหรับโมดูล ขอบคุณ!
จิม

ฉันดีใจที่ได้ผลกับคุณ ฉันใช้เทคนิคเดียวกันเพื่อแก้ไขข้อผิดพลาดในการส่งข้อความ เป็นทางเลือกฉันเพิ่งค้นพบgit notes นี้จะให้บริการวัตถุประสงค์เดียวกันเป็น "errata กระทำ" เพียงเพิ่มบันทึกย่อในการคอมมิชชันก่อนหน้านี้เพื่อเพิ่มความคิดเห็นหรือแก้ไขข้อผิดพลาดใด ๆ ในข้อความคอมมิชชัน: https://git-scm.com/docs/git-notes
rob_7cc

0

มันใช้งานได้ดีสำหรับฉัน

git checkout กำเนิด / branchname

หากคุณอยู่ในสาขาแล้วควรดึงหรือรีบูตดีกว่า

git pull

หรือ

git -c core.quotepath=false fetch origin --progress --prune

หลังจากนั้นคุณสามารถใช้

git commit --amend -m "Your message here"

หรือหากคุณต้องการเปิดโปรแกรมแก้ไขข้อความให้ใช้

git commit --amend

ฉันจะชอบใช้โปรแกรมแก้ไขข้อความหากคุณมีความคิดเห็นมากมาย คุณสามารถตั้งค่า text-editor ที่คุณต้องการด้วยคำสั่ง

git config --global core.editor your_preffered_editor_here

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

จากนั้นเรียกใช้

git push --force

และคุณทำเสร็จแล้ว


0

ข้อมูลเพิ่มเติมสำหรับปัญหาเดียวกันหากคุณใช้งานท่อ bitbucket

แก้ไขข้อความของคุณ

git commit --amend

ผลักไปที่ตัด

git push --force <repository> <branch>

จากนั้นเพิ่ม - บังคับให้คำสั่ง push ของคุณบนไปป์ไลน์

git ftp push --force

การดำเนินการนี้จะลบการกระทำก่อนหน้าของคุณและผลักดันรายการปัจจุบันของคุณ

ลบ --force หลังจากกดครั้งแรก

ฉันลองมันบนท่อ bitbucket และมันใช้งานได้ดี

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