Git, viết lại tên người dùng và email cam kết trước đó


170

Tôi đã cam kết một loạt các cam kết cho một dự án trên Github, tuy nhiên tôi nhận ra rằng tôi đã thiết lập email đầy đủ và tên đầy đủ của người đăng ký trên máy tính mà tôi hiện đang sử dụng để thực hiện các cam kết của mình và do đó, hình đại diện và địa chỉ email của người dùng Không có ở đó.

Làm cách nào tôi có thể viết lại tất cả các email và tên người dùng trước đây?



Tôi đã trải nghiệm điều này sau khi thay đổi địa chỉ email trên tài khoản GitHub của mình. Ngoài việc thay đổi mã từ repo git cục bộ bằng giao diện dòng lệnh git (chứ không phải giao diện GitHub), tôi cũng chỉnh sửa văn bản và quản lý tệp trực tiếp từ repo git từ xa bằng giao diện web GitHub. Địa chỉ email mới chỉ được truyền đến các cam kết phát sinh từ các hành động sau chứ không phải trước đó.
Robert John

Câu trả lời:


243

Bạn có thể thêm bí danh này:

git config alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f "

Để thay đổi tên tác giả:

git change-commits GIT_AUTHOR_NAME "old name" "new name"

hoặc email chỉ cho 10 lần xác nhận gần nhất:

git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com" HEAD~10..HEAD

Bí danh:

change-commits="!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" \$@; }; f "

Nguồn: https://github.com/bAFiobo/gitconfig/blob/master/configs/.gitconfig


13
Ngoài ra git change-commits GIT_COMMITTER_EMAIL "old@example.com" "new@example.com"để thay đổi email committer.
nguyệt quế

19
đã sửa cho "eval: [[: không tìm thấy" trên change-commits = "!f() { VAR1=$1; VAR='$'$1; OLD=$2; NEW=$3; echo \"Are you sure for replace $VAR $OLD => $NEW ?(Y/N)\";read OK;if [ \"$OK\" = 'Y' ] ; then shift 3; git filter-branch --env-filter \"if [ \\\"${VAR}\\\" = '$OLD' ]; then export $VAR1='$NEW';echo 'to $NEW'; fi\" $@; fi;}; f "
ubfox

9
git: 'thay đổi-cam kết' không phải là lệnh git. Xem 'git - trợ giúp'. Có nghĩa là bạn chưa thêm bí danh vào cấu hình git của mình. ví dụ: git config -e
Wayne

2
Điều này chỉ tạo ra các bản sao của tất cả các cam kết với email tôi muốn thay đổi. Không xuất hiện để viết lại lịch sử. Giải pháp của @Olivier Verdier đã làm việc cho tôi.
Jake Wilson

6
Thực hiện hai lần liên tiếp với các đầu vào khác nhau dẫn đến:Cannot create a new backup. A previous backup already exists in refs/original/
theonlygusti

97

Giải pháp đã có: Thay đổi tên tác giả và tên người gửi và e-mail của nhiều lần xác nhận trong Git

Cụ thể là

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

4
Điều này sẽ không thay đổi tên tác giả cho tất cả các cam kết (toàn bộ lịch sử) của chi nhánh?
hasen

2
Vâng, điều đó sẽ thay đổi tất cả các cam kết với thông tin tác giả mới.
ewall

9
Vui lòng đánh dấu các câu hỏi là trùng lặp thay vì sao chép câu trả lời.
givanse

2
Nếu tôi không chỉ định tên cũ hoặc email cũ thì sao? git nói "danh tính trống <> không được phép"
Griffan

Tôi đã chạy lệnh này và bây giờ repo của tôi sẽ không được đẩy hoặc kéo từ máy chủ git.
Chúa Giêsu H

46

Nếu bạn đã đẩy một số cam kết của mình vào kho lưu trữ công cộng, bạn không muốn làm điều này hoặc nó sẽ tạo một phiên bản thay thế của lịch sử của chủ nhân mà những người khác có thể đã sử dụng. "Đừng băng qua suối ... Sẽ rất tệ ..."

Điều đó nói rằng, nếu đó chỉ là những cam kết bạn đã thực hiện với kho lưu trữ cục bộ của mình, thì bằng mọi cách hãy khắc phục điều này trước khi bạn đẩy lên máy chủ. Bạn có thể sử dụng git filter-branchlệnh với --commit-filtertùy chọn, vì vậy nó chỉ chỉnh sửa các xác nhận khớp với thông tin không chính xác của bạn, như thế này:

git filter-branch --commit-filter '
      if [ "$GIT_AUTHOR_EMAIL" = "wrong_email@wrong_host.local" ];
      then
              GIT_AUTHOR_NAME="Your Name Here (In Lights)";
              GIT_AUTHOR_EMAIL="correct_email@correct_host.com";
              git commit-tree "$@";
      else
              git commit-tree "$@";
      fi' HEAD

5
Điều này hoạt động hoàn hảo trong khi câu trả lời được đánh dấu bằng màu xanh lá cây thì không
jmary

Sau đó, người ta có thể muốn xóa bản sao lưu với git update-ref -d refs/original/refs/heads/master, xem < stackoverflow.com/a/7654880/333403 >.
cknoll

FYI: Nếu bạn có nhiều tên / email không chính xác, bạn có thể cần phải chạy nhiều lần. Nếu điều đó xảy ra, nó sẽ rên rỉ với bạn với lỗi này: A previous backup already exists in refs/original/Trong trường hợp đó, hãy chạy lại nó, với email mới và thêm một -ftrước bộ lọc --commit. Sử dụng theo quyết định của riêng bạn. Thông thường -flà một điều nguy hiểm để làm mà không có kiến ​​thức về những gì nó đang làm.
Chuck

19

Sau khi áp dụng câu trả lời của Olivier Verdier:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

... Để đẩy lịch sử đã thay đổi trên kho lưu trữ ban đầu, hãy sử dụng:

git push origin +yourbranch

Lệnh trên (lưu ý dấu cộng) cũng viết lại lịch sử trên repo gốc. Sử dụng cẩn thận!


Làm việc cho tôi, cũng viết lại chính xác lịch sử về nguồn gốc.
Xeverous

10
Điều này sẽ viết lại TẤT CẢ các cam kết - bất kể ai là tác giả của nó. Sử dụng cẩn thận.
Bhavin Doshi

14

https://help.github.com/articles/changing- Author-info /

#!/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="oldEmail@xxx-MacBook-Pro.local"
CORRECT_NAME="yourName"
CORRECT_EMAIL="yourEmail"

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

điều này hoàn toàn làm việc cho tôi Sau khi đẩy git, hãy đảm bảo xem cập nhật trên cổng web của git. Nếu cam kết vẫn không được liên kết với tài khoản của tôi, được hiển thị hình ảnh thu nhỏ mặc định bên cạnh cam kết và nó không được phản ánh trên biểu đồ dòng thời gian đóng góp của tôi, hãy đi tới url cam kết và nối .patch ở cuối url và xác minh tên và email là chính xác.


Trong khi về mặt lý thuyết có thể trả lời câu hỏi, tốt hơn là nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo.
jhpratt

1
Đây là người duy nhất viết lại tất cả các chi nhánh.
Bruno Zell

6

Đối với những người chỉ muốn phiên bản sao chép dán dễ dàng (ngoài việc cập nhật email và tên):

git config alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f "
git change-commits GIT_AUTHOR_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_AUTHOR_EMAIL <old@email.com> <new@email.com> -f
git change-commits GIT_COMMITTER_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_COMMITTER_EMAIL <old@email.com> <new@email.com> -f

5
-bash :! f: không tìm thấy sự kiện
Saiyine

Rất có thể là một vấn đề với một thiết bị đầu cuối thoát mọi thứ tự động
Andrei Savin

3

Xem xét việc sử dụng git-filter-branchkhông mong muốn , để làm điều tương tự trong git-filter-repo (bạn có thể cần phải cài đặt nó trước pip install git-filter-repo):

git-filter-repo --name-callback 'return name.replace(b"OldName", b"NewName")' --email-callback 'return email.replace(b"old@email.com", b"new@email.com")'

Nếu kho lưu trữ là bản gốc, từ xa, bạn sẽ phải thêm --forceđể buộc viết lại. (Bạn có thể muốn tạo bản sao lưu repo của mình trước khi thực hiện việc này.)

Nếu bạn không muốn duy trì refs (chúng sẽ được hiển thị trong lịch sử chi nhánh của GUI Git), bạn sẽ phải thêm --replace-refs delete-no-add.

Để biết các tính năng nâng cao hơn, hãy xem "Lọc tên và email" .

PS bị đánh cắp và cải thiện từ https://stackoverflow.com/a/59591928/714907 .

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.