แก้ไขการคอมมิทใน Git หรือไม่


328

มีวิธีในการเปลี่ยนข้อความจากการกระทำในภายหลัง:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

คุณสามารถเปลี่ยนข้อความการส่งข้อความของการส่งข้อความครั้งแรก (ซึ่งไม่มีพาเรนต์) ได้อย่างไร



โดยเฉพาะอย่างยิ่ง: การใช้ตัวแปรสภาพแวดล้อม GIT_COMMIT ในสคริปต์ของgit filter-branch --msg-filter
fork0

คำตอบ:


284

สมมติว่าคุณมีต้นไม้ทำงานที่สะอาดคุณสามารถทำสิ่งต่อไปนี้

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master

23
git rebase --onto HEAD <sha1-of-root> masterผมเชื่อว่านี่ควรจะเป็น
Andrew

5
ขวา แต่คุณต้องการเดิมรากกระทำสำหรับ <ต้นน้ำ> git rebaseของ git rebaseใช้ความมุ่งมั่นใน <branch> ( master) ที่ไม่ได้อยู่ใน <upstream>; HEADไม่ได้อยู่ในดังนั้นรุ่นพยายามของคุณที่จะใช้ทั้งหมดของmaster master
Andrew

7
ใช่ให้แน่ใจว่าของgit rebase --onto HEAD <sha1-of-root>ต้นแบบที่เป็นเช่นเดียวกับที่ใช้ในการ<sha1-of-root> git checkout <sha1-of-root>มิฉะนั้นคุณจะมี 2 first commit's
Andy

2
@Cupcake: คุณทดสอบคำสั่งเวอร์ชันเก่าหรือไม่? มันควรจะทำงานได้ดี การแก้ไขกำลังเปลี่ยนข้อความการส่งข้อมูลเพื่อให้รูทเก่าและใหม่คอมมิทแนะนำการเปลี่ยนแปลงที่เหมือนกันดังนั้นการคอมมิชชันเก่าจะถูกข้ามโดยอัตโนมัติ ที่สองHEADช่วยให้มั่นใจได้ว่าการคอมมิททั้งหมดนั้นได้รับการพิจารณาและเราสามารถใช้การรีเวอร์ชัน rebase ทั้งสองพารามิเตอร์เพื่อย้ายกลับไปที่มาสเตอร์ โปรดทราบว่าคำตอบนี้มาก่อน--rootตัวเลือกที่จะรีบูต
CB Bailey

9
คำตอบของ ecdpalmaด้านล่างนั้นง่ายกว่าและเรียบง่ายกว่าและมีคะแนนโหวตมากขึ้นเลื่อนคนลงไป!
Flimm

567

ในฐานะของ Git รุ่น1.7.12ตอนนี้คุณสามารถใช้

git rebase -i --root

เอกสาร


2
เป็นไปได้ไหมที่จะรีบู๊ทของกิ่งไม้ทั้งหมดโดยใช้คำสั่งนี้? ดูเหมือนว่าสิ่งนี้จะแยกกิ่งปัจจุบันออกจากรากใหม่และกิ่งอื่น ๆ ทั้งหมดจะอยู่บนรากเก่า
woojoo666

@ woojoo666 คุณจะต้องทำการ rebase branch ไปยังรูทใหม่แล้ว เหมือนอย่างเคย.
เบอร์กัส

@ ยอดขายไม่สามารถใช้งานได้หากไม่มีรูทอัปสตรีม
Kai

คำเตือน: ฉันสันนิษฐานผิดว่านี่จะทำให้รูทของสาขาที่ฉันเช็คเอาต์ แต่ใช้เวลาสักครู่เพื่อโหลดคอมมิททั้งหมดจากนั้นรีบูตพวกเขาทั้งหมด
Leo

2
@Leo ความคิดเห็นของคุณหมายถึงอะไร ฉันไม่เห็นลิงก์ระหว่างส่วนแรกและส่วนที่สองสิ่งที่ต้องทำในขณะนั้นต้องทำอย่างไร
boycy

66

เพื่อขยายคำตอบของ ecdpalmaตอนนี้คุณสามารถใช้--rootตัวเลือกเพื่อบอกrebaseว่าคุณต้องการเขียนรูท / คอมมิทใหม่อีกครั้ง:

git rebase --interactive --root

จากนั้นคอมมิชชันรูทจะปรากฏในรายการสิ่งที่ต้องทำ rebase และคุณสามารถเลือกที่จะแก้ไขหรือใส่คำซ้ำได้:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

นี่คือคำอธิบายของ--rootจากเอกสารรีบูต Git (เน้นที่เหมือง):

Rebase กระทำทั้งหมดที่สามารถเข้าถึงได้จาก<branch>แทนที่จะ จำกัด <upstream>พวกเขาด้วยนี้ช่วยให้คุณ rebase รากกระทำ (s) ในสาขา


12

เพียงเพื่อให้ทางเลือกแก่คำตอบที่ได้รับคะแนนสูงกว่า:

หากคุณกำลังสร้าง repo และรู้ล่วงหน้าว่าคุณจะได้รับส่วนลดจากการกระทำที่แท้จริง "ครั้งแรก" ในอนาคตคุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยการทำคอมมิชชันว่างไว้ตอนต้น:

git commit --allow-empty -m "Initial commit"

และจากนั้นก็เริ่มทำ "จริง" มุ่งมั่น จากนั้นคุณสามารถรีบูทบนวิธีที่ได้มาตรฐานเช่นgit rebase -i HEAD^


4
ไม่ได้หมายความว่าในการสั่งซื้อสำหรับการทำงาน, คุณจะต้องมีการมองการณ์ไกล (หรือจะกายสิทธิ์) เพื่อให้ที่ว่างเปล่ากระทำที่เหมาะสมในจุดเริ่มต้นมากของโครงการของคุณ ? นี้น่าจะเป็นสถานการณ์มากให้ฉันและโดยทั่วไปไม่ได้ในทางปฏิบัติ คุณคิดอย่างไร? จะเกิดอะไรขึ้นถ้าฉันได้ทำไปแล้ว 100 ครั้งและฉันก็ต้องแก้ไขการคอมมิท ในกรณีนี้ฉันจะยังใช้งานได้ไหมถ้าฉันไม่ได้ทำคอมเม้นท์เปล่าตอนเริ่มต้น?

2
การแก้ไขข้อความของ root ที่กระทำนั้นอาจไม่ใช่สิ่งที่คุณจะทำหลังจากมี 100s บางครั้งฉันก็แค่อยากจะมี repo คอมไพล์ทำถังขยะกระทำบางอย่างรู้ว่าเมื่อฉันถึงสถานะที่ใช้งานได้บางฉันจะสควอชพวกเขาเป็นหนึ่งเช่นกันและ reword ข้อความ อย่างไรก็ตามตอนนี้ฉันเปลี่ยนใจและฉันคิดว่าสิ่งที่มีประโยชน์มากที่สุดสำหรับการคอมมิทครั้งแรกคือการวาง.gitattributesไฟล์แทนที่จะทำคอมมิทเปล่า ๆ
jakub.g

4

คุณสามารถใช้git filter-branch:

cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit

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