Làm cách nào để chỉnh sửa lịch sử của git để sửa địa chỉ email / tên không chính xác [đã đóng]


76

Khi tôi bắt đầu sử dụng git, tôi chỉ cần làm một git initvà bắt đầu gọi addcommit. Bây giờ tôi bắt đầu chú ý và tôi có thể thấy rằng các cam kết của tôi đang hiển thị cowens@localmachine, thay vì địa chỉ tôi muốn. Nó xuất hiện như thể thiết lập GIT_AUTHOR_EMAILGIT_COMMITTER_EMAILsẽ làm những gì tôi muốn, nhưng tôi vẫn có những cam kết cũ với địa chỉ email / tên sai. Làm thế nào tôi có thể sửa các cam kết cũ?


4
Đối với độc giả tương lai của chúng tôi: Các câu hỏi về việc sử dụng gitcho các mục đích tương tự như thế này được hỏi tốt hơn về Stack Overflow .
Michael Hampton

Đây là câu hỏi gần nhất trên stackoverflow.com.
ness101

Câu trả lời:


82

Bạn có thể quay lại và sửa tất cả các cam kết của mình bằng một cuộc gọi đến chi nhánh bộ lọc git. Điều này có tác dụng tương tự như rebase, nhưng bạn chỉ cần thực hiện một lệnh để sửa tất cả lịch sử của mình, thay vì sửa từng cam kết riêng lẻ.

Bạn có thể sửa tất cả các email sai bằng lệnh này:

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

Thêm thông tin có sẵn từ các tài liệu git


11
tốt, git bộ lọc-nhánh --env-filter 'export GIT_AUTHOR_EMAIL = "foo@example.com"; GIT_AUTHOR_NAME = "Foo"' đơn giản hơn rất nhiều, cảm ơn. Đây sẽ là câu trả lời được chấp nhận nếu tôi có thể thay đổi nó (có vẻ như có lỗi với Server Fault).
Chas. Owens

7
Lưu ý rằng các dòng xuất KHÔNG nên có khoảng trắng ở hai bên của dấu bằng. Tức là họ nên trông như thế này: export GIT_AUTHOR_EMAIL = "(email chính xác)";
Andy Balaam

1
Bây giờ, làm thế nào tôi có thể làm điều này trên Windows?
Carsten Schmitz

2
@Deckard: lưu tập lệnh vào một tệp văn bản như fixcommits.sh, sau đó chạy Git Bash và chạy tập lệnh. Tôi đặt tệp tập lệnh vào thư mục gốc của repo của mình, sau đó điều hướng đến thư mục đó trong Git Bash, sau đó tôi chạy tập lệnh với ./fixcommits.sh
Avalanchis

2
Phụ lục 1 Định dạng lệnh này không hiệu quả với tôi, nhưng nếu / thì đã làm:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.

28

Lệnh nhánh bộ lọc của Git rất mạnh, nhưng thật khó sử dụng cho bất kỳ thứ gì không tầm thường, chẳng hạn, nếu bạn có nhiều hơn một tác giả để sửa.

Đây là một thay thế tôi thấy hữu ích, sử dụng tính năng .mailmap được mô tả trong trang quản lý git-shortlog. Điều này cung cấp một cơ chế ánh xạ tác giả mà chúng ta có thể sử dụng với cơ sở định dạng của git log. Chúng ta có thể sử dụng nó để tạo các lệnh để chọn và sửa đổi sửa đổi một chuỗi các cam kết được đặt tên.

Ví dụ: giả sử bạn muốn sửa quyền tác giả trên chi nhánh $ CHI NHÁNH, bắt đầu từ một cam kết $ START.

Bạn cần tạo một tệp .mailmap trong thư mục trên cùng của kho lưu trữ để ánh xạ tên tác giả hiện có thành tên chính xác. Bạn có thể nhận danh sách tên tác giả hiện có với:

git shortlog -se

Bạn cần kết thúc với một tệp .mailmap như thế này (giả sử):

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

Bây giờ bạn có thể sử dụng tính năng định dạng của nhật ký git để tạo các lệnh để viết lại $ BRANCH thành $ BRANCH2.

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

Lệnh đầu tiên tạo ra một nhánh trống mới mọc lên từ cam kết $ START. Đối với mỗi cam kết giữa $ START và sau đó là kết thúc $ BRANCH, lệnh thứ hai cherry chọn cam kết ban đầu vào cuối nhánh hiện tại $ BRANCH2 và sửa đổi nó để đặt chính xác cho tác giả.

Điều này cũng thường được áp dụng - hãy đặt cái này trong ~ / .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" '

Vì vậy, khi bạn cần sửa các tác giả, bây giờ bạn chỉ cần tạo một .mapfile và làm:

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

Tham chiếu nhánh gốc có thể được gán lại cho cái mới và cái mới bị xóa:

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

Điều này thật tuyệt. Tôi sẽ trả tiền cho bạn nếu tôi có nhiều đại diện hơn. Cảm ơn :)
pistache

9

Kết hợp câu trả lời từ Làm cách nào để sửa lỗi siêu dữ liệu trên lần cam kết đầu tiên trong 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 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

Đưa tôi đi đúng hướng, nhưng cần lệnh từ: stackoverflow.com/a/28536828/307 thay vì sử dụng
Brett Veenstra

5

Để làm theo câu trả lời của jedberg: Bạn có thể sử dụng rebase -ivà chọn chỉnh sửa các cam kết trong câu hỏi. Nếu bạn sử dụng git commit --amend --author <AUTHOR DETAILS>và sau đó git rebase continuebạn có thể đi qua và sửa chữa lịch sử.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.