Bagaimana cara mengedit riwayat git untuk memperbaiki alamat / nama email yang salah [ditutup]

76

Ketika saya mulai menggunakan git saya hanya melakukan git initdan mulai menelepon adddan commit. Sekarang saya mulai memperhatikan dan saya dapat melihat bahwa komitmen saya muncul sebagai cowens@localmachine, bukan alamat yang saya inginkan. Tampaknya pengaturan GIT_AUTHOR_EMAILdan GIT_COMMITTER_EMAILakan melakukan apa yang saya inginkan, tetapi saya masih memiliki komitmen lama dengan alamat / nama email yang salah. Bagaimana saya bisa memperbaiki komitmen lama?

Chas. Owens
sumber
4
Untuk pembaca kami di masa depan: Pertanyaan tentang penggunaan gituntuk tujuan yang serupa dengan ini lebih baik ditanyakan pada Stack Overflow .
Michael Hampton
Inilah pertanyaan terdekat di stackoverflow.com.
naught101

Jawaban:

82

Anda dapat kembali dan memperbaiki semua komitmen Anda dengan satu panggilan ke git filter-branch. Ini memiliki efek yang sama dengan rebase, tetapi Anda hanya perlu melakukan satu perintah untuk memperbaiki semua riwayat Anda, alih-alih memperbaiki setiap komit secara individual.

Anda dapat memperbaiki semua email yang salah dengan perintah ini:

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

Informasi lebih lanjut tersedia dari git docs

andy
sumber
11
baik, git-cabang-filter --env-filter 'ekspor GIT_AUTHOR_EMAIL = "[email protected]"; GIT_AUTHOR_NAME = "Foo"' jauh lebih sederhana, terima kasih. Ini akan menjadi jawaban yang diterima jika saya bisa mengubahnya (sepertinya ada bug dengan Server Fault).
Chas. Owens
7
Perhatikan bahwa jalur ekspor TIDAK boleh memiliki spasi di kedua sisi tanda sama dengan. Yaitu mereka akan terlihat seperti ini: export GIT_AUTHOR_EMAIL = "(email yang benar)";
Andy Balaam
1
Sekarang, bagaimana saya melakukan ini pada Windows?
Carsten Schmitz
2
@Deckard: simpan skrip ke file teks seperti fixcommits.sh, kemudian jalankan Git Bash dan jalankan skrip. Saya meletakkan file skrip di root repo saya, lalu menavigasi ke folder itu di Git Bash, kemudian saya menjalankan skrip dengan ./fixcommits.sh
Avalanchis
2
Tambahan 1 Format perintah ini tidak berfungsi untuk saya, tetapi jika / kemudian dilakukan:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.
28

Perintah cabang-filter Git sangat kuat, tetapi sangat sulit digunakan untuk hal-hal yang tidak sepele, seperti misalnya, jika Anda memiliki lebih dari satu penulis yang harus dikoreksi.

Inilah alternatif yang menurut saya berguna, yang menggunakan fitur .mailmap yang dijelaskan dalam halaman git-shortlog. Ini menyediakan mekanisme pemetaan penulis yang dapat kita gunakan dengan fasilitas pemformatan git log. Kita dapat menggunakannya untuk menghasilkan perintah untuk memilih dan mengubah mengubah urutan komit.

Sebagai contoh, misalkan Anda ingin memperbaiki kepengarangan pada cabang $ CABANG, mulai dari $ MULAI komit.

Anda perlu membuat file .mailmap di direktori teratas repositori Anda yang memetakan nama penulis yang sudah ada untuk mengoreksi. Anda bisa mendapatkan daftar nama penulis yang ada dengan:

git shortlog -se

Anda harus memiliki file .mailmap seperti ini (misalnya):

You <[email protected]>   cowens@localmachine
You <[email protected]>   root@localmachine

Sekarang Anda dapat menggunakan fitur pemformatan git log untuk menghasilkan perintah untuk menulis ulang $ BRANCH sebagai $ BRANCH2.

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

Perintah pertama membuat cabang kosong baru yang tumbuh dari komit $ MULAI. Untuk setiap komit antara $ MULAI dan kemudian akhir dari $ CABANG, perintah kedua cherry mengambil komit asli ke akhir cabang saat ini $ CABANG2, dan mengubah itu untuk mengatur penulis dengan benar.

Ini juga berlaku secara umum - letakkan ini di ~ / .gitconfig Anda:

[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" '

Jadi ketika Anda perlu memperbaiki penulis, sekarang Anda hanya perlu menghasilkan .mapfile dan lakukan:

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

Ref cabang asli dapat dipindahkan ke yang baru, dan yang baru dihapus:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
wu-lee
sumber
Ini luar biasa. Aku akan memberimu hadiah jika aku punya lebih banyak perwakilan. Terima kasih :)
pistache
9

Menggabungkan jawaban dari Bagaimana cara memperbaiki metainformation pada komit pertama di git?

### 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 [email protected]"
# (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 [email protected]"
# (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
Chas. Owens
sumber
Membuat saya di jalur yang benar, tetapi membutuhkan perintah dari: stackoverflow.com/a/28536828/307 sebagai ganti --author use
Brett Veenstra
5

Untuk mengikuti jawaban jedberg: Anda dapat menggunakan rebase -idan memilih untuk mengedit komit yang dimaksud. Jika Anda menggunakan git commit --amend --author <AUTHOR DETAILS>dan kemudian git rebase continueAnda dapat melewati dan memperbaiki sejarah.

Chealion
sumber