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


76

เมื่อผมเริ่มใช้คอมไพล์ผมก็ไม่ได้git initและเริ่มเรียกและadd commitตอนนี้ฉันเริ่มให้ความสนใจและฉันสามารถเห็นได้ว่าคำมั่นสัญญาของฉันแสดงเป็นcowens@localmachineมากกว่าที่อยู่ที่ฉันต้องการ ดูเหมือนว่าการตั้งค่าGIT_AUTHOR_EMAILและGIT_COMMITTER_EMAILจะทำในสิ่งที่ฉันต้องการ แต่ฉันก็ยังคงมีข้อผูกมัดเก่ากับที่อยู่อีเมล / ชื่อที่ไม่ถูกต้อง ฉันจะแก้ไขคอมมิชชันเก่าได้อย่างไร


4
สำหรับผู้อ่านของเราในอนาคต: คำถามเกี่ยวกับการใช้gitเพื่อวัตถุประสงค์ที่คล้ายกันนี้จะถูกถามที่ดีขึ้นในกองมากเกิน
Michael Hampton

คำตอบ:


82

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

คุณสามารถแก้ไขอีเมลที่ไม่ถูกต้องทั้งหมดด้วยคำสั่งนี้:

git filter-branch --env-filter '
    oldname="(old name)"
    oldemail="(old email)"
    newname="(new name)"
    newemail="(new email)"
    [ "$GIT_AUTHOR_EMAIL"="$oldemail" ] && GIT_AUTHOR_EMAIL="$newemail"
    [ "$GIT_COMMITTER_EMAIL"="$oldemail" ] && GIT_COMMITTER_EMAIL="$newemail"
    [ "$GIT_AUTHOR_NAME"="$oldname" ] && GIT_AUTHOR_NAME="$newname"
    [ "$GIT_COMMITTER_NAME"="$oldname" ] && GIT_COMMITTER_NAME="$newname"
    ' HEAD

ข้อมูลเพิ่มเติมสามารถดูได้จากเอกสาร git


11
ดี git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL = "foo@example.com"; GIT_AUTHOR_NAME = "Foo"' นั้นง่ายกว่ามากขอบคุณ นี่จะเป็นคำตอบที่ยอมรับได้ถ้าฉันสามารถเปลี่ยนได้ (ดูเหมือนว่ามีข้อผิดพลาดกับ Server Fault)
Chas Owens

7
โปรดทราบว่าสายการส่งออกไม่ควรมีช่องว่างที่ด้านข้างของเครื่องหมายเท่ากับ นั่นคือพวกเขาควรมีลักษณะเช่นนี้: ส่งออก GIT_AUTHOR_EMAIL = "(อีเมลที่ถูกต้อง)";
Andy Balaam

1
ตอนนี้ฉันจะทำสิ่งนี้บน Windows ได้อย่างไร
Carsten Schmitz

2
@Deckard: บันทึกสคริปต์ลงในไฟล์ข้อความเช่น fixcommits.sh จากนั้นเรียกใช้ Git Bash และเรียกใช้สคริปต์ ฉันวางไฟล์สคริปต์ไว้ในรูทของ repo ของฉันจากนั้นไปที่โฟลเดอร์นั้นใน Git Bash จากนั้นฉันก็รันสคริปต์ด้วย. /fixcommits.sh
Avalanchis

2
ภาคผนวก 1รูปแบบคำสั่งนี้ใช้ไม่ได้สำหรับฉัน แต่ถ้าเป็นเช่นนั้น:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.

28

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

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

ตัวอย่างเช่นสมมติว่าคุณต้องการแก้ไขการเขียนในสาขา $ สาขาโดยเริ่มจากการยอมรับ $ START

คุณต้องสร้างไฟล์. mailmap ในไดเรกทอรีบนสุดของที่เก็บของคุณซึ่งจะจับคู่ชื่อผู้แต่งที่มีอยู่กับเขาให้ถูกต้อง คุณสามารถรับรายชื่อผู้แต่งที่มีอยู่ด้วย:

git shortlog -se

คุณต้องจบด้วยไฟล์. mailmap เช่นนี้ (พูด):

You <you@somewhere.org>   cowens@localmachine
You <you@somewhere.org>   root@localmachine

ตอนนี้คุณสามารถใช้คุณสมบัติการจัดรูปแบบของบันทึกการคอมไพล์เพื่อสร้างคำสั่งเพื่อเขียน $ BRANCH เป็น $ BRANCH2

git checkout -b $BRANCH2 $START
git log --reverse --pretty=format:"cherry-pick %H; commit --amend --author='%aN <%aE>' -C %H" $START..$BRANCH | sh - 

คำสั่งแรกสร้างสาขาใหม่ที่ว่างเปล่าแตกหน่อจากการกระทำ $ START สำหรับการคอมมิทแต่ละครั้งระหว่าง $ START ถึงตอนท้ายของ $ BRANCH คำสั่งที่สองเชอร์รี่จะเลือกคอมมิชชันดั้งเดิมจนถึงจุดสิ้นสุดของสาขาปัจจุบัน $ BRANCH2 และแก้ไขเพื่อตั้งค่าผู้เขียนให้ถูกต้อง

โดยทั่วไปยังสามารถใช้งานได้ - ใส่สิ่งนี้ใน ~ / .gitconfig ของคุณ:

[alias]
    # git reauthor $START..$END
    reauthor = !sh -c 'eval `git log --reverse --topo-order --pretty=format:\"git cherry-pick %H &&  git commit --amend -C %H --author=\\\"%aN <%aE>\\\" && \" $0 ` "echo success" '

ดังนั้นเมื่อคุณต้องการแก้ไขผู้เขียนตอนนี้คุณเพียงแค่ต้องสร้าง. mapfile และทำ:

git checkout -b $BRANCH2 $START
git reauthor $START..$BRANCH

การอ้างอิงสาขาเดิมสามารถกำหนดใหม่ให้กับสาขาใหม่และสาขาใหม่ที่ถูกลบ:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2

นี่มันเจ๋งมาก. ฉันจะให้รางวัลคุณถ้าฉันมีตัวแทนมากขึ้น ขอบคุณ :)
pistache

9

การรวมคำตอบจากฉันจะแก้ไข metainformation ในการคอมมิทครั้งแรกได้อย่างไร?

### Fix the first commit ###    
# create a temporary tag for the root-most commit so we can reference it
git tag root `git rev-list HEAD | tail -1`
# check it out on its own temporary branch
git checkout -b new-root root
# amend the commit
git commit --amend --author "Foo foo@example.com"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# now you've changed the commit message, so checkout the original branch again
git checkout @{-1}
# and rebase it onto your new root commit
git rebase --onto new-root root
### Fix the rest of the commits ###
git rebase -i root
# edit the file to read "edit <commit number> for each entry
# amend the commit
git commit --amend --author "Foo foo@example.com"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# move to the next commit
git rebase --continue    
# continue running the last two commands until you see
# Successfully rebased and updated refs/heads/master.
### Clean up ###
# nuke the temporary branch we created
git branch -d new-root
# nuke the temporary tag we created
git tag -d root

ให้ฉันในการติดตามที่ถูกต้อง แต่ต้องใช้คำสั่งจาก: stackoverflow.com/a/28536828/307แทนการใช้ --author
Brett Veenstra

5

หากต้องการทำตามคำตอบของ jedberg: คุณสามารถใช้rebase -iและเลือกแก้ไขข้อผูกพันที่เป็นปัญหาได้ หากคุณใช้git commit --amend --author <AUTHOR DETAILS>และจากนั้นgit rebase continueคุณสามารถผ่านและแก้ไขประวัติ

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