Câu hỏi Làm thế nào để thay đổi tác giả cam kết cho một cam kết cụ thể?


Tôi muốn thay đổi tác giả của một cam kết cụ thể trong lịch sử. Nó không phải là cam kết cuối cùng.

Tôi biết về câu hỏi này - Làm thế nào để thay đổi tác giả của một cam kết trong git?

Nhưng tôi đang suy nghĩ về một cái gì đó, nơi tôi xác định các cam kết bằng băm hoặc băm ngắn.


1388
2018-06-15 04:00


gốc


Có thể trùng lặp Làm cách nào để sửa đổi các cam kết hiện có, chưa được xóa? - tkruse


Các câu trả lời:


Tương tác rebase off của một điểm trước đó trong lịch sử hơn so với cam kết bạn cần phải sửa đổi (git rebase -i <earliercommit>). Trong danh sách các cam kết được rebased, thay đổi văn bản từ pick đến edit bên cạnh giá trị băm bạn muốn sửa đổi. Sau đó, khi git nhắc bạn thay đổi cam kết, hãy sử dụng lệnh này:

git commit --amend --author="Author Name <email@address.com>"

Ví dụ: nếu lịch sử cam kết của bạn là A-B-C-D-E-F với F như HEADvà bạn muốn thay đổi tác giả của C và Dthì bạn sẽ ...

  1. Chỉ định git rebase -i B (đây là một ví dụ về những gì bạn sẽ thấy sau khi thực hiện git rebase -i B chỉ huy)
    • nếu bạn cần chỉnh sửa A, sử dụng git rebase -i --root
  2. thay đổi các dòng cho cả hai C và D từ pick đến edit
  3. Khi khởi động lại, nó sẽ tạm dừng ở C
  4. Bạn muốn git commit --amend --author="Author Name <email@address.com>"
  5. Sau đó git rebase --continue
  6. Nó sẽ tạm dừng lại ở D
  7. Sau đó, bạn sẽ git commit --amend --author="Author Name <email@address.com>" lần nữa
  8. git rebase --continue
  9. Việc rebase sẽ hoàn thành.

2330
2018-06-15 04:31



Câu trả lời hay, nhưng đối với người mới bắt đầu: trước tiên hãy tìm một cam kết trước cam kết bạn muốn thay đổi, sau đó chạy git rebase -i <commit> - Mathew Byrne
Nếu bạn không biết bạn đang biên tập gì, câu trả lời có khả năng vim. Để lưu và thoát, gõ Esc: w q Enter. Mặt khác, nếu nó là Nano và bạn thấy những thứ như "WriteOut: ^ O" dọc theo phía dưới, thì bạn nên sử dụng Ctrl + O, Enter, Ctrl + X thay vào đó. - Amber
nếu bạn muốn thay đổi cam kết đầu tiên thì sao? Băm cam kết trước đó là gì? - Brenden
Sử dụng --no-edit Tùy chọn. git commit --amend --reset-author --no-edit sẽ không mở một trình soạn thảo. Có sẵn từ git 1.7.9. - 5lava
@Brenden để sửa đổi cam kết đầu tiên trong dự án, sử dụng git rebase -i --root - Noah Passalacqua


Các câu trả lời được chấp nhận cho câu hỏi này là sử dụng tuyệt vời thông minh của rebase tương tác, nhưng nó không may trưng bày xung đột nếu cam kết chúng tôi đang cố gắng để thay đổi tác giả của được sử dụng để được trên một chi nhánh mà sau đó đã được sáp nhập. Nói chung, nó không hoạt động khi xử lý lộn xộn lịch sử.

Vì tôi e ngại về việc chạy các tập lệnh phụ thuộc vào việc thiết lập và hủy các biến môi trường để viết lại lịch sử git, tôi đang viết một câu trả lời mới dựa trên bài này tương tự như câu trả lời này nhưng hoàn chỉnh hơn.

Sau đây là thử nghiệm và làm việc, không giống như câu trả lời liên kết. Giả sử cho sự rõ ràng của giải thích rằng 03f482d6 là cam kết mà tác giả chúng tôi đang cố gắng thay thế và 42627abe là cam kết với tác giả mới.

  1. Kiểm tra cam kết mà chúng tôi đang cố sửa đổi.

    git checkout 03f482d6
    
  2. Làm cho tác giả thay đổi.

    git commit --amend --author "New Author Name <New Author Email>"
    

    Bây giờ chúng tôi có một cam kết mới với hàm băm được giả định là 42627abe.

  3. Thanh toán chi nhánh ban đầu.

  4. Thay thế các cam kết cũ với một địa phương mới.

    git replace 03f482d6 42627abe
    
  5. Viết lại tất cả các cam kết trong tương lai dựa trên sự thay thế.

    git filter-branch -- --all
    
  6. Loại bỏ các thay thế cho sự sạch sẽ.

    git replace -d 03f482d6
    
  7. Đẩy lịch sử mới (chỉ sử dụng - force nếu dưới đây thất bại, và chỉ sau khi kiểm tra sanity với git log và / hoặc git diff).

    git push --force-with-lease
    

Thay vì 4-6 bạn chỉ có thể rebase vào cam kết mới:

git rebase -i 42627abe

315
2018-03-04 02:11



Vui lòng ghi chú vào đó để thanh toán lại chi nhánh ban đầu của bạn sau bước 2. - Benjamin Riggs
Điều này có vẻ thay thế rõ ràng cho khủng khiếp git rebase -i. Chưa bao giờ nghe nói về điều này git replace điều trước đây. +1 - FractalSpace
Để làm sạch refs / original / ... sao lưu xem đây - alexis
Tôi khuyên bạn nên sử dụng --force-with-lease thay vì -f. Nó an toàn hơn. - Jay Bazuzi
@ merlin2011, cảm ơn vì bài đăng tuyệt vời. Tôi thực sự đã thử nó và nó hoạt động rất tốt, nhưng với một thay đổi nhỏ: sau git replace -d trong Step 5 một git checkout master lệnh có vẻ là cần thiết. Nếu không, tôi vẫn đang ở trên một chi nhánh chưa được đặt tên và git push không hoạt động ở đó. suy nghĩ của bạn về điều đó là gì? - Lukasz Czerwinski


Tài liệu Github chứa một tập lệnh thay thế thông tin người gửi cho tất cả các cam kết trong một chi nhánh.

#!/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"

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

130
2018-06-09 16:02



Điều này thay đổi nó trong tất cả các cam kết, không chỉ là một. Điều thú vị, tôi đã làm điều này ít hơn 30 phút trước. - Artjom B.
Khi tôi tìm thấy câu trả lời này sau khi đọc những câu trả lời trước đó, tôi nghĩ rằng nó đáng để thử và thì đấy là công việc. Tuy nhiên trong trường hợp của tôi nó đã thay đổi tên người nhận chỉ trong cam kết ban đầu. Nhân tiện, trước khi tôi thử ý tưởng từ câu trả lời đầu tiên. Có lẽ nó ảnh hưởng đến hệ thống bằng cách nào đó. - Ruslan Gerasimov
git push -f kết thúc phép thuật. Cảm ơn vì viên ngọc này! - andrej
Lưu ý rằng nếu bạn tránh sử dụng clone / push, bạn sẽ kết thúc với một không gian tên sao lưu refs/original/. Tôi không thể tìm cách xóa bỏ không gian tên này một cách thông minh, vì vậy tôi đã xóa thư mục .git/refs/original , đã hoạt động. - VasyaNovikov


Bạn có thể thay đổi tác giả của lần commit cuối cùng bằng cách sử dụng lệnh dưới đây.

git commit --amend --author="Author Name <email@address.com>"

Tuy nhiên, nếu bạn muốn thay đổi nhiều hơn một tên tác giả, nó hơi phức tạp một chút. Bạn cần phải bắt đầu một rebase tương tác sau đó đánh dấu các cam kết như chỉnh sửa sau đó ammend chúng từng người một và kết thúc.

Bắt đầu rebasing với git rebase -i. Nó sẽ cho bạn thấy một cái gì đó như thế này.

https://monosnap.com/file/G7sdn66k7JWpT91uiOUAQWMhPrMQVT.png

Thay đổi pick từ khóa đến edit cho các cam kết bạn muốn thay đổi tên tác giả.

https://monosnap.com/file/dsq0AfopQMVskBNknz6GZZwlWGVwWU.png

Sau đó đóng trình chỉnh sửa. Đối với người mới bắt đầu, nhấn Escape sau đó nhập :wq va đanh Enter.

Sau đó, bạn sẽ thấy thiết bị đầu cuối của bạn như không có gì xảy ra. Trên thực tế bạn đang ở giữa một rebase tương tác. Bây giờ là lúc sửa đổi tên tác giả của bạn bằng cách sử dụng lệnh trên. Nó sẽ mở lại trình chỉnh sửa. Thoát và tiếp tục rebase với git rebase --continue. Lặp lại tương tự cho số cam kết bạn muốn chỉnh sửa. Bạn có thể đảm bảo rằng quá trình rebase tương tác kết thúc khi bạn nhận được No rebase in progress? thông điệp.


60
2017-08-29 00:52





  • Đặt lại email của bạn thành cấu hình trên toàn cầu:

    git config --global user.email example@email.com

  • Bây giờ hãy đặt lại tác giả của cam kết của bạn mà không cần chỉnh sửa:

    git commit --amend --reset-author --no-edit


54
2018-04-05 12:44



Không, không phải. Nhìn vào OP: It's not last commit. Vậy làm thế nào họ có thể amend nó? - underscore_d
Điều này là tuyệt vời, đó là một sự xấu hổ đó là cam kết cuối cùng chỉ, mặc dù. Tôi cần nó trên hai mới nhất, may mắn thay, vì vậy chỉ cần làm một git reset HEAD~, chạy các dòng được đề xuất của bạn, sau đó thực hiện lại lần commit tiếp theo. Làm việc tốt! - Matt Fletcher


Các câu trả lời trong câu hỏi mà bạn liên kết là những câu trả lời hay và bao gồm hoàn cảnh của bạn (câu hỏi khác là tổng quát hơn vì nó liên quan đến việc viết lại nhiều commit).

Như một cái cớ để thử git filter-branch, Tôi đã viết một kịch bản để viết lại tên tác giả và / hoặc email tác giả cho một cam kết cụ thể:

#!/bin/sh

#
# Change the author name and/or email of a single commit.
#
# change-author [-f] commit-to-change [branch-to-rewrite [new-name [new-email]]]
#
#     If -f is supplied it is passed to "git filter-branch".
#
#     If <branch-to-rewrite> is not provided or is empty HEAD will be used.
#     Use "--all" or a space separated list (e.g. "master next") to rewrite
#     multiple branches.
#
#     If <new-name> (or <new-email>) is not provided or is empty, the normal
#     user.name (user.email) Git configuration value will be used.
#

force=''
if test "x$1" = "x-f"; then
    force='-f'
    shift
fi

die() {
    printf '%s\n' "$@"
    exit 128
}
targ="$(git rev-parse --verify "$1" 2>/dev/null)" || die "$1 is not a commit"
br="${2:-HEAD}"

TARG_COMMIT="$targ"
TARG_NAME="${3-}"
TARG_EMAIL="${4-}"
export TARG_COMMIT TARG_NAME TARG_EMAIL

filt='

    if test "$GIT_COMMIT" = "$TARG_COMMIT"; then
        if test -n "$TARG_EMAIL"; then
            GIT_AUTHOR_EMAIL="$TARG_EMAIL"
            export GIT_AUTHOR_EMAIL
        else
            unset GIT_AUTHOR_EMAIL
        fi
        if test -n "$TARG_NAME"; then
            GIT_AUTHOR_NAME="$TARG_NAME"
            export GIT_AUTHOR_NAME
        else
            unset GIT_AUTHOR_NAME
        fi
    fi

'

git filter-branch $force --env-filter "$filt" -- $br

46
2018-06-15 05:24



1 cảm ơn. assembla.com git repo không xuất hiện để thay đổi tất cả các tài liệu tham khảo tác giả trong chế độ xem web của repo, nhưng kết quả của 'git pull / clone' xuất hiện cho tất cả công việc ok. - Johnny Utahh
Giải pháp tuyệt vời, vì nó chỉ thay đổi những gì được dự định và không phải là các trường khác, như ngày cam kết. - Guillaume Lemaître
Tài liệu Github chứa kịch bản tương tự - olivieradam666
@ olivieradam666 hoạt động như một sự quyến rũ và dễ đọc hơn - bfred.it
@seane Tôi đã thêm câu trả lời mới - olivieradam666


Khi làm git rebase -i có một chút thú vị trong tài liệu:

Nếu bạn muốn gấp hai hoặc nhiều cam kết thành một, thay thế lệnh "pick" cho các cam kết thứ hai và tiếp theo với "squash" hoặc là "fixup". Nếu các cam kết có các tác giả khác nhau, cam kết gấp sẽ được gán cho tác giả của lần commit đầu tiên. Thông báo cam kết được đề xuất cho cam kết gấp là kết nối của các thông báo cam kết của lần commit đầu tiên và của các thông báo commit "squash" lệnh, nhưng bỏ qua thông báo cam kết cam kết với "fixup" chỉ huy.

  • Nếu bạn có một lịch sử A-B-C-D-E-F,
  • và bạn muốn thay đổi cam kết B và D (= 2 cam kết),

thì bạn có thể làm:

  • git config user.name "Correct new name"
  • git config user.email "correct@new.email"
  • tạo các cam kết trống (một cho mỗi cam kết):
    • bạn cần một tin nhắn cho mục đích rebase
    • git commit --allow-empty -m "empty"
  • bắt đầu hoạt động rebase
    • git rebase -i B^
    • B^ chọn phụ huynh của B.
  • bạn sẽ muốn đặt một cam kết trống trước mỗi cam kết sửa đổi
  • bạn sẽ muốn thay đổi pick đến squash cho những người.

Ví dụ về những gì git rebase -i B^ sẽ cung cấp cho bạn:

pick sha-commit-B some message
pick sha-commit-C some message
pick sha-commit-D some message
pick sha-commit-E some message
pick sha-commit-F some message
# pick sha-commit-empty1 empty
# pick sha-commit-empty2 empty

thay đổi điều đó thành:

# change commit B's author
pick sha-commit-empty1 empty
squash sha-commit-B some message
# leave commit C alone
pick sha-commit-C some message
# change commit D's author
pick sha-commit-empty2 empty
squash sha-commit-D some message
# leave commit E-F alone
pick sha-commit-E some message
pick sha-commit-F some message

Nó sẽ nhắc bạn chỉnh sửa tin nhắn:

# This is a combination of 2 commits.
# The first commit's message is:

empty

# This is the 2nd commit message:

...some useful commit message there...

và bạn chỉ có thể xóa một vài dòng đầu tiên.


12
2017-08-28 01:03





Có một bước bổ sung để Câu trả lời của Amber nếu bạn đang sử dụng kho lưu trữ tập trung:

git push -f để buộc cập nhật kho lưu trữ trung tâm.

Hãy cẩn thận rằng không có nhiều người làm việc trên cùng một chi nhánh bởi vì nó có thể làm hỏng sự nhất quán.


11
2017-12-20 15:06



Đó là một bình luận không phải là một câu trả lời - vsync


Cam kết trước:

enter image description here

Để khắc phục tác giả cho tất cả các cam kết, bạn có thể áp dụng lệnh từ câu trả lời của @ Amber:

git commit --amend --author="Author Name <email@address.com>"

Hoặc để sử dụng lại tên và email của bạn, bạn chỉ cần viết:

git commit --amend --author=Eugen

Cam kết sau lệnh:

enter image description here

Ví dụ để thay đổi tất cả bắt đầu từ 4025621:

enter image description here

Bạn phải chạy:

git rebase --onto 4025621 --exec "git commit --amend --author=Eugen" 4025621

hoặc thêm bí danh này vào ~/.gitconfig:

[alias]
    reauthor = !bash -c 'git rebase --onto $1 --exec \"git commit --amend --author=$2\" $1' --

Và sau đó chạy:

git reauthor 4025621 Eugen

1
2018-06-30 12:16