วิธีแก้ไขหลายคอมมิทใน Git เพื่อเปลี่ยนผู้เขียน


180

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

ฉันได้รับการดูgit resetและgit commit -C <id> --reset-authorแต่ฉันไม่คิดว่าฉันในการติดตามขวา


1
อีกเหตุผลที่คุณอาจต้องการเปลี่ยนคุณสมบัติอีเมลก็คือข้อผิดพลาด gitub นี้: remote: error: GH007: Your push would publish a private email address.... `! [การปฏิเสธจากระยะไกล] master -> master (การกดปฏิเสธเนื่องจากข้อ จำกัด ความเป็นส่วนตัวทางอีเมล) `
craq

ยังเห็นstackoverflow.com/q/750172/1340631
scai

คำตอบ:


232

การลด / แก้ไขดูเหมือนว่าไม่มีประสิทธิภาพเมื่อคุณมีพลังของตัวกรองสาขาที่ปลายนิ้วของคุณ:

git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = "incorrect@email" ]; then
     GIT_AUTHOR_EMAIL=correct@email;
     GIT_AUTHOR_NAME="Correct Name";
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
     GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all

(แยกข้ามเส้นเพื่อความชัดเจน แต่ไม่จำเป็น)

อย่าลืมตรวจสอบผลลัพธ์เมื่อเสร็จเพื่อให้แน่ใจว่าคุณไม่ได้เปลี่ยนแปลงอะไรที่คุณไม่ได้ตั้งใจ!


ใจอธิบายเพิ่มเติมอีกเล็กน้อยไหม ไม่แน่ใจว่าสาขาตัวกรองคืออะไร
สูงสุด pleaner

1
@maxpleaner git filter-branch --helpค่อนข้างตรงไปตรง :) :)
alediaferia

3
ดูhelp.github.com/articles/changing-author-infoซึ่งยังเพิ่ม--tag-name-filter catไปfilter-branchเพื่อที่จะแท็กโยกย้ายไปยังประวัติศาสตร์ใหม่ นอกจากนี้ยังใช้--branches --tagsแทน--allซึ่งจะเขียนเฉพาะสาขาและประวัติแท็กและปล่อยให้refsอยู่คนเดียว (แม้ว่าอาจจะไม่ได้สร้างความแตกต่างมากนักยกเว้นว่าคุณกำลังใช้git-notes)
Tobias Kienzler

12
ในการดำเนินการเกี่ยวกับเรื่องนี้เพียงสองกระทำที่ผ่านมาฉันแทนที่-- --allด้วยHEAD~1..HEAD
nmz787

1
@ nmz787 หลายวิธีบันทึกจะแสดงถ้าคุณทำgit log HEAD~2..HEAD?
Jona

148

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

ก่อนอื่นให้ตั้งค่าผู้แต่ง git ของคุณ

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

จากนั้นให้รีเซ็ตผู้แต่งสำหรับการกระทำทั้งหมดหลังจาก SHA ที่กำหนด

git rebase -i YOUR_SHA -x "git commit --amend --reset-author -CHEAD"

สิ่งนี้จะปรากฏขึ้นบรรณาธิการของคุณเพื่อยืนยันการเปลี่ยนแปลง สิ่งที่คุณต้องทำที่นี่คือการบันทึกและออกและมันจะผ่านแต่ละการกระทำและเรียกใช้คำสั่งที่ระบุในแฟล็ก -x

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

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"

3
ขอบคุณที่แนะนำฉันให้กับตัวเลือก -x มันยอดเยี่ยมมาก! สำหรับตัวเลือก -i ฉันใช้ HEAD ~ 4 เพื่อแก้ไขที่อยู่อีเมลของฉันในการกระทำ 4 ครั้งล่าสุดของฉัน ทำงานเหมือนจับใจ
แบรดไฮน์

2
มันง่ายกว่าfilter-branchถ้าคุณแค่ต้องการแก้ไขการมอบหมายครั้งสุดท้าย :) อย่างไรก็ตามโปรดทราบว่านี่เป็นการเปลี่ยนแปลงการประทับเวลาของการส่งข้อความ
luator

24
หากต้องการเปลี่ยนผู้แต่ง แต่ดูแลรักษาการประทับเวลาดั้งเดิมให้ใช้git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"
Dave

2
@Connor git logยังมีผลงานเก่าสำหรับฉัน แต่สถานะคอมไพล์ได้ระบุอย่างถูกต้องแล้วและหลังจากที่พวกเขาถูกบังคับ
Dan M.

6
หากต้องการรีบูตการกระทำทั้งหมดรวมถึงการใช้รูท: git rebase -i --root …แทนที่จะส่งผ่าน SHA
gfullam

80

หากต้องการเปลี่ยนผู้แต่งเฉพาะสำหรับการส่งครั้งล่าสุด:

git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

สมมติว่าคุณต้องการเปลี่ยนผู้เขียนสำหรับการยอมรับ N ครั้งล่าสุดเท่านั้น:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

หมายเหตุ

  • --no-editธงทำให้แน่ใจว่าgit commit --amendไม่ได้ขอการยืนยันการพิเศษ
  • เมื่อคุณใช้git rebase -iคุณสามารถเลือกกระทำที่จะเปลี่ยนผู้เขียนด้วยตนเอง

ไฟล์ที่คุณแก้ไขจะมีลักษณะเช่นนี้:

pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix

1
สำหรับการกระทำทั้งหมดจากราก git rebase -i - รูท UPTO_COMMIT_SHA -x "คอมมิทกระทำ - แก้ไข
Ashish Negi

1
ฉันขอแนะนำให้เพิ่มตัวเลือก--rebase-merges(สั้น ๆ-r) เพื่อให้โทโพโลยีของสาขาของคุณไม่บุบสลายหากมีการผสานบางอย่าง
donquixote

4

วิธีนี้ได้รับการบันทึกโดย github เพื่อจุดประสงค์นี้ ขั้นตอนคือ:

  1. เปิดสถานีและทำให้เปลือยโคลนของ repo ของคุณ
git clone --bare https://github.com/user/repo.git
cd repo
  1. แก้ไขสคริปต์ต่อไปนี้ (เปลี่ยนOLD_EMAIL, CORRECT_EMAILและCORRECT_NAME)
#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
  1. คัดลอก / วางสคริปต์ลงในเทอร์มินัลแล้วกด Enter เพื่อเรียกใช้
  2. ผลักดันการเปลี่ยนแปลงของคุณด้วยgit push --force --tags origin 'refs/heads/*'และคุณทำเสร็จแล้ว!

ฉันทำตามคำแนะนำเดียวกันกับ GitHub ที่คุณอ้างอิงและ GitHub ดูตอนนี้ อย่างไรก็ตามฉันเป็น Git newb และไม่แน่ใจว่าจะซิงค์ข้อมูลซื้อคืนภายในเครื่องของฉันได้อย่างไรหลังจากนั้น เมื่อฉันดึงฉันจะได้รับข้อผิดพลาด "ปฏิเสธที่จะรวมประวัติที่ไม่เกี่ยวข้อง" ซึ่งกล่าวถึงในคำตอบอื่น ฉันคิดว่าฉันจำเป็นต้อง rebase กับประวัติศาสตร์การส่งมอบครั้งนั้น แต่ฉันซาบซึ้งกับขั้นตอนที่เฉพาะเจาะจงมากขึ้น
enigment

@enigment ถ้าคุณมีความสุขกับธุรกรรมซื้อคืนในขณะที่มันอยู่บน GitHub คุณสามารถลบ (หรืออาจจะย้ายไปยังตำแหน่งอื่น) โฟลเดอร์ที่คุณมีในประเทศและเพียงแค่โคลนจาก GitHub
stevec

ขอบคุณฉันรู้ แต่นั่นไม่เหมือนวิธี GitHub / Git ที่เป็นสำนวน
enigment

2

ฉันเชื่อว่าสิ่งที่คุณกำลังมองหาคือ git rebase --interactive

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

ที่นี่คุณมีคำอธิบายhttps://web.archive.org/web/20100213104931/http://blog.madism.org/index.php/2007/09/09/138-git-awsome-ness-git-rebase -เชิงโต้ตอบ


0

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

git reset HEAD~ (เลิกทำการคอมมิชชันล่าสุด)

git config --global user.name "Your Name"

git config --global user.email you@example.com

git commit -m "message"

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