Tôi có thể thay đổi tên và họ của mình trong tất cả các lần xác nhận trước không?


122

Tôi muốn thay đổi tên, họ và email trong tất cả các cam kết của mình, điều đó có thể không?


2
Đó có phải là một sự phản đối chỉ dành cho bạn, cho một vài người hoặc cho một dự án lớn?
thejh



Câu trả lời:


212

Sử dụng git-filter-branch.

git filter-branch --commit-filter 'if [ "$GIT_AUTHOR_NAME" = "Josh Lee" ];
  then export GIT_AUTHOR_NAME="Hobo Bob"; export GIT_AUTHOR_EMAIL=hobo@example.com;
  fi; git commit-tree "$@"'

Điều này chỉ ảnh hưởng đến tác giả, không phải tác giả (mà đối với hầu hết các cam kết sẽ giống như tác giả). Nếu bạn cũng muốn viết lại chúng, hãy đặt GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILcác biến.

Các cảnh báo tiêu chuẩn về viết lại lịch sử áp dụng; chỉ làm điều đó với lịch sử chưa được chia sẻ.

Cập nhật tháng 6 năm 2018

Hướng dẫn hiện bao gồm một giải pháp, sử dụng --env-filter, trong các ví dụ của nó: https://git-scm.com/docs/git-filter-branch#_examples :

git filter-branch --env-filter '
    if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
    then
        GIT_AUTHOR_EMAIL=john@example.com
    fi
    if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
    then
        GIT_COMMITTER_EMAIL=john@example.com
    fi
' -- --all

4
Nếu bạn đang sử dụng msysgit, bạn vẫn có quyền truy cập bash. Mặt khác, tôi không có manh mối.
Josh Lee

@Joshua nếu bạn đang sử dụng thứ gì đó mà bạn không có bash, có lẽ bạn có thể sử dụng kịch bản hàng loạt của windows, mặc dù tôi chưa thử.
MatrixFrog

và những gì về thẻ? giải pháp này sẽ không thay đổi tác giả của các thẻ
piotrek

@Joshua kiểm tra repo git trên hộp linux và thực hiện sửa lỗi ở đó
Will Sheppard

Có một tùy chọn dẫn đến chi nhánh mới và giữ nguyên nguồn cam kết không?
Eugen Konkov

56

Để viết lại cả tác giả và commiter trong tất cả các cam kết đã chọn:

git filter-branch --commit-filter \
'if [ "$GIT_AUTHOR_NAME" = "OldAuthor Name" ]; then \
export GIT_AUTHOR_NAME="Author Name";\
export GIT_AUTHOR_EMAIL=authorEmail@example.com;\
export GIT_COMMITTER_NAME="Commmiter Name";\
export GIT_COMMITTER_EMAIL=commiterEmail@example.com;\
fi;\
git commit-tree "$@"'

1
Nhưng làm thế nào để áp dụng thay đổi cho máy chủ từ xa?
vikyd

5
@Viky Hãy thửgit push --all origin --force
user11153

2
Nó làm việc cho tôi! Tôi đang sử dụng GitLab, tôi phải bảo vệ chi nhánh trước khi đẩy lệnh.
vikyd

37

Nếu không có tác giả khác, bạn có thể làm:

git filter-branch --commit-filter 'export GIT_AUTHOR_NAME="authorname"; \
export GIT_AUTHOR_EMAIL=mail@example.com; git commit-tree "$@"'

1
Đó không phải là viết lại thông tin "Committer:".
dùng11153

1
Nó không có ý định viết lại thông tin người đi làm. Nếu bạn muốn làm điều đó, hãy xuất GIT_COMMITTER_NAME và GIT_COMMITTER_EMAIL (xem câu trả lời được chấp nhận).
bấm giờ

12

Lưu tập lệnh bên dưới như ví dụ ~/.bin/git-replace-authorvà chạy nó bằng cách sử dụng, ví dụ:

git replace-author "John Ssmith" "John Smith" "johnsmith@example.com"

Không có đối số, nó cập nhật tất cả các cam kết với tên của bạn để sử dụng địa chỉ email hiện tại của bạn theo cấu hình Git.

DEFAULT_NAME="$(git config user.name)"
DEFAULT_EMAIL="$(git config user.email)"
export OLD_NAME="${1:-$DEFAULT_NAME}"
export NEW_NAME="${2:-$DEFAULT_NAME}"
export NEW_EMAIL="${3:-$DEFAULT_EMAIL}"

echo "Old:" $OLD_NAME "<*>"
echo "New:" "$NEW_NAME <$NEW_EMAIL>"
echo "To undo, use: git reset $(git rev-parse HEAD)"

git filter-branch --env-filter \
'if [ "$GIT_AUTHOR_NAME" = "${OLD_NAME}" ]; then
    export GIT_AUTHOR_NAME="${NEW_NAME}"
    export GIT_AUTHOR_EMAIL="${NEW_EMAIL}"
    export GIT_COMMITTER_NAME="${NEW_NAME}"
    export GIT_COMMITTER_EMAIL="${NEW_EMAIL}"
fi'

Nguyên (để tải về)


Như một lưu ý ngắn: ~/.bin/cần phải ở bên trong người dùng $PATHvà tệp cần được thực thi, vì vậy hãy chạy : chmod +x ~/.bin/git-replace-author.
Michael Gecht

Và nó làm gì với các đối số?
Eugen Konkov

2

Chỉ khi bạn không đẩy cam kết của mình ra thế giới. Những người khôn ngoan khác có tên cũ của bạn trong repo của họ mà không chắc bạn có thể thay đổi tên của mọi người.


Đúng, nhưng trong một số trường hợp bạn không có sự lựa chọn. Tôi là trường hợp của tôi, tôi đã có một địa chỉ email sai được cấu hình trong cấu hình git của tôi (như tôi có thể thấy với "git config --global -l"). Do đó, tôi không có hoạt động cam kết nào hiển thị trong repo Github của riêng tôi (vì địa chỉ email không khớp với email được định cấu hình trong Github)! Để giải quyết vấn đề này, tôi đã sửa lỗi cam kết cục bộ của mình bằng cách sử dụng công thức từ stackoverflow.com/a/23564785/2474068 (hoạt động hoàn hảo) và sau đó tôi đã đẩy các cam kết đã thay đổi thành Github bằng cách sử dụng "git push -u -f origin master" (với lực lượng cờ "-f"). Điều đó đi ngược lại thực tế được chấp nhận nhưng tôi không có lựa chọn!
leo

1
Vâng, quan điểm của tôi là bất kỳ nhánh nào của repo đó sẽ không có sự thay đổi đó trừ khi họ chấp nhận lực đẩy của bạn. Sẽ rất khó khăn để có được mọi ngã ba để cập nhật :)
EnabrenTane

1

Với Git 2.24 (Q4 2019), git filter-branch(và BFG) không được dùng nữa .

Tương đương sẽ là, sử dụng newren/git-filter-repophần ví dụ của nó :

cd repo
git filter-repo --mailmap my-mailmap

với my-mailmap:

Correct Name <correct@email.com> <old@email.com>

Điều đó sẽ thay thế tên tác giả và email của bất kỳ cam kết nào được thực hiện bởi bất kỳ ai với <old@email.com>

Xem git shortlogphần tác giả ánh xạ cho cú pháp chính xác của

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.