ฉันจะแก้ไขข้อความคอมมิทที่ไม่ถูกต้องเป็นคอมไพล์ได้อย่างไร


152

ฉันต้องการแก้ไขข้อความคอมมิชชันที่ลึกลงไปในประวัติศาสตร์และฉันได้เพิ่มความมุ่งมั่นใหม่ ๆ

ฉันจะเปลี่ยนข้อความยืนยันได้อย่างไร เป็นไปได้ไหม?

คำตอบ:


125

ข้อความจาก Linus Torvalds อาจตอบคำถามของคุณ:

แก้ไข / แก้ไขข้อความคอมมิชชันเก่า

คำตอบสั้น ๆ : คุณไม่สามารถ (ถ้าผลัก)


สารสกัด (Linus หมายถึง BitKeeper เป็น BK):

บันทึกข้างเคียงไม่สนใจประวัติศาสตร์: ใน BK คุณทำได้

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

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

แต่ฉันไม่ได้

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

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

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


เพื่อให้เสร็จสมบูรณ์คุณสามารถเขียนประวัติการกระทำในท้องถิ่นของคุณใหม่เพื่อสะท้อนสิ่งที่คุณต้องการตามที่ sykora แนะนำ (พร้อมรีบูตและรีเซ็ท - ฮาร์ด, อ้าปากค้าง!)

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

แยกออกจากคำถาม SO อื่น ๆ นี้:

จริง ๆ แล้วฉันเคยผลักด้วย --force ไปยังที่เก็บ git.git และถูกดุโดย Linus BIG TIME มันจะสร้างปัญหามากมายให้กับคนอื่น คำตอบง่ายๆคือ "อย่าทำ"


คำตอบที่ดี. คุณรู้หรือไม่ว่าตอนนี้คุณสามารถเปลี่ยนข้อความที่ส่งไปแล้วใน git เวอร์ชันใหม่กว่าได้หรือไม่? มีอะไรเปลี่ยนแปลงบ้างนับตั้งแต่มีการโพสต์ในปี '09?
David West

@DavidWest มีหลักการเดียวกัน: คุณสามารถเขียนประวัติของคุณใหม่และบังคับให้มีการผลักดัน
VonC

2
เพื่อให้สิ่งต่าง ๆ มีความเฉพาะเจาะจงมากขึ้นถ้าคุณแก้ไข / rebits กระทำตัวระบุการกระทำ (แฮชเลขฐานสิบหกในดัชนี git) จะเปลี่ยนแปลงอย่างหลีกเลี่ยงไม่ได้ หมายความว่าคอมมิทที่แก้ไขนั้นได้รับการปฏิบัติแตกต่างจากคอมมิชชันเก่าในประวัติ VCS คอมไพล์ กล่าวกันว่าหากสมาชิกในทีม dev ของคุณโชคไม่ดีที่ได้ดึงคอมมิชชันเก่ามาแล้วพวกเขาจำเป็นต้องดึงคอมมิชชันที่แก้ไขใหม่และทำการผสานระหว่างเก่ากับใหม่ในสำเนางานท้องถิ่นของพวกเขา
Shigerello

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

28

ขณะนี้การแทนที่คอมไพล์อาจทำเคล็ดลับ

รายละเอียด: สร้างสาขางานชั่วคราว

git checkout -b temp

รีเซ็ตเป็นคอมมิตที่จะแทนที่

git reset --hard <sha1>

แก้ไขการกระทำด้วยข้อความที่ถูกต้อง

git commit --amend -m "<right message>"

แทนที่การคอมมิชชันเก่าด้วยอันใหม่

git replace <old commit sha1> <new commit sha1>

กลับไปที่สาขาที่คุณอยู่

git checkout <branch>

ลบสาขา temp

git branch -D temp

ดัน

guess

เสร็จแล้ว


11
@Jonah: ฉันได้รับข้อความ "ทุกอย่างที่ทันสมัย" เมื่อฉันพยายามที่จะผลักดันไปยังสาขาระยะไกล
Simon Kagwi

1
ตามที่กล่าวไว้ในคำตอบอื่น: ใช้ rebase -i กับ reword และมันจะเขียนประวัติศาสตร์ใหม่อีกครั้ง
Sylvain

ขอบคุณสำหรับวิธีแก้ปัญหาซึ่งฉันกำลังมองหา คุณประหยัดเวลาของฉัน!
Tomasz Kuter

1
@Jonah - ฉันมีปัญหา ... วิธีแก้ปัญหาของคุณอัปเดตบันทึกการคอมมิชชันของฉันในเครื่อง แต่ไม่ใช่จากระยะไกล วิธีการผลักดันพวกเขามี?
Tomasz Kuter

1
@TomaszKuter ฉันมีปัญหาเช่นเดียวกับคุณ ข้อความยืนยันของฉันไม่ได้รับการอัปเดตจากระยะไกล ฉันจะแก้ไขได้โดยใช้ความช่วยเหลือต่อไปนี้จาก GitHub: help.github.com/articles/changing-a-commit-message ทำตาม: การแก้ไขข้อความของข้อความที่เก่ากว่าหรือหลายการคอมมิต เป็นพื้นคำตอบจากด้านล่างที่กำหนดโดยผู้ใช้ 987419 ถ้าคุณเปลี่ยนข้อความคอมมิทคุณสามารถทำการเลือกและบันทึกโดยไม่ต้องเปลี่ยนอีก
evaldeslacasa

19

คุณสามารถใช้git rebase -i(กับสาขาที่คุณแยกจาก) 'i' สำหรับการโต้ตอบ

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

git push อีกครั้งและคุณทำเสร็จแล้ว!


1
การดำเนินการนี้ไม่อนุญาตให้มีการแก้ไขข้อความในการรวมการกระทำ เป็นไปได้ไหมที่มีความแตกต่างของคำสั่งนี้?
Andrew Mao

1
ลอง-pโต้แย้งrebaseว่าการpรวมกันของการสำรอง
กระบองเพชร

3
ฉันชอบขั้นตอนนี้ แต่ไม่เข้าใจคำตอบในตอนแรก ในกรณีที่มีคนต้องการความช่วยเหลือหน้าความช่วยเหลือ Githulb ให้ข้อมูลที่ดีเกี่ยวกับมัน: help.github.com/articles/changing-a-commit-message
evaldeslacasa

15

สมมติว่าคุณมีต้นไม้แบบนี้:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]

ครั้งแรกcheckoutสาขาชั่วคราว:

git checkout -b temp

ในtempสาขาreset --hardการกระทำที่คุณต้องการเปลี่ยนข้อความ (ตัวอย่างเช่นการกระทำนั้น946992):

git reset --hard 946992

ใช้amendเพื่อเปลี่ยนข้อความ:

git commit --amend -m "<new_message>"

หลังจากนั้นต้นไม้จะมีลักษณะเช่นนี้:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
           \
            b886a0 [temp]

จากนั้นคอมมิทcherry-pickทั้งหมดที่อยู่ก่อนหน้า946992จากmasterถึงtempและคอมมิทใช้amendถ้าคุณต้องการเปลี่ยนข้อความด้วย:

git cherry-pick 9143a9
git commit --amend -m "<new_message>
...
git cherry-pick 5a6057
git commit --amend -m "<new_message>

ตอนนี้ต้นไม้มีลักษณะดังนี้:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
               \
                b886a0 - 41ab2c - 6c2a3s - 7c88c9 [temp]

ตอนนี้บังคับให้ดัน temp branch ไปที่รีโมต:

git push --force origin temp:master

ขั้นตอนสุดท้ายสาขาลบmasterในท้องถิ่นgit fetch originไปยังสาขาดึงmasterจากเซิร์ฟเวอร์จากนั้นสลับไปสาขาและสาขาลบmastertemp

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


5

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

แม้ว่านี่จะไม่ได้ช่วยคนที่ใช้คำสั่ง "git log" แบบไม่เป็นทางการ แต่ก็มีวิธีแก้ไขการอ้างอิงตัวติดตามบั๊กที่ไม่ถูกต้องในความคิดเห็นและเครื่องมือสร้างและวางจำหน่ายของฉันทั้งหมดเข้าใจหลักการ

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


3
"บันทึก git" อาจตอบสนองวัตถุประสงค์ที่คล้ายกัน
Christian Goetze

2

(จากhttp://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0 )

วิธีการเปลี่ยนแปลงมุ่งมั่นลึกลงไปในประวัติศาสตร์

เนื่องจากประวัติใน Git นั้นไม่สามารถแก้ไขได้ แต่การแก้ไขใด ๆ แต่การกระทำล่าสุด (การกระทำที่ไม่ใช่หัวหน้าสาขา) ทำให้ต้องมีการเขียนประวัติใหม่จากการส่งและการส่งต่อที่เปลี่ยนแปลงไป

คุณสามารถใช้ StGIT เพื่อเริ่มต้นสาขาได้หากจำเป็นไม่ต้องรับภาระถึงการยอมรับที่คุณต้องการเปลี่ยนให้ป๊อปอัปหากจำเป็นทำการเปลี่ยนแปลงแล้วรีเฟรชแพทช์ (ด้วยตัวเลือก -e หากคุณต้องการแก้ไขการส่งข้อความ) จากนั้นกด ทุกอย่างและ stg กระทำ

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

หรือคุณสามารถใช้ git rebase - แบบอินเทอร์แอคทีฟซึ่งอนุญาตให้แก้ไขได้หลายแบบเช่นการสั่งแพทช์ใหม่การยุบ ...

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


คำตอบที่ดีในทางทฤษฎีอันตรายที่ยิ่งใหญ่ในทางปฏิบัติ: ดูstackoverflow.com/questions/253055#432518
VonC

0

หากคุณใช้ Git Extensions: เข้าไปที่หน้าจอ Commit ควรมีช่องทำเครื่องหมายที่ระบุว่า "แก้ไขการกระทำ" ที่ด้านล่างดังที่เห็นด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่


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