Come cambiare l'autore del commit per un commit specifico?

Voglio cambiare l'autore di uno specifico commit nella storia. Non è l'ultimo commit.

So di questa domanda - Come posso cambiare l'autore di un commit in git?

Ma sto pensando a qualcosa, dove identifico il commit per hash o short-hash.

Soluzione

Il rebase interattivo parte da un punto precedente nella storia rispetto al commit che devi modificare (git rebase -i). Nella lista dei commit in fase di rebase, cambia il testo da pick a edit accanto all'hash di quello che vuoi modificare. Poi quando git ti chiede di cambiare il commit, usa questo:

git commit --amend --author="Author Name "

Per esempio, se la tua cronologia di commit è A-B-C-D-E-F con F come HEAD, e vuoi cambiare l'autore di C e D, allora dovresti...

  1. Specificate git rebase -i B (ecco un esempio di ciò che vedrete dopo l'esecuzione del comando git rebase -i B)
  • se hai bisogno di modificare A, usa git rebase -i --root
  1. cambia le linee per entrambi i comandi C e D da pick a edit
  2. Una volta che il rebase è iniziato, si fermerà prima a C.
  3. Dovreste git commit --amend --author="Nome Autore "
  4. Poi git rebase --continue.
  5. Si fermerebbe di nuovo a D.
  6. Poi dovreste git commit --amend --author="Nome Autore " di nuovo
  7. git rebase --continue.
  8. Il rebase verrebbe completato.
  9. Usa git push -f per aggiornare la tua origine con i commit aggiornati.
Commentari (44)

Le risposte nella domanda a cui ti sei collegato sono buone risposte e coprono la tua situazione (l'altra domanda è più generale poiché implica la riscrittura di più commit).

Come scusa per provare git filter-branch, ho scritto uno script per riscrivere il nome dell'autore e/o l'email dell'autore per un dato commit:

#!/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  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  (or ) 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
Commentari (9)

Quando si fa git rebase -i c'è questo pezzo interessante nel documento:

Se vuoi piegare due o più commit in uno solo, sostituisci il comando "pick" per il secondo e i successivi commit con "squash" o "fixup". Se i commit hanno autori diversi, il commit ripiegato sarà attribuito all'autore del primo commit. Il messaggio di commit suggerito per il folded commit è la concatenazione dei messaggi di commit del primo commit e di quelli con il comando "squash", ma omette i messaggi di commit dei commit con il comando "fixup".

  • Se hai una cronologia di A-B-C-D-E-F,
  • e vuoi cambiare i commit B e D (= 2 commit),

allora puoi fare:

  • git config user.name "Corretto nuovo nome"
  • git config user.email "correct@new.email"
  • crea dei commit vuoti (uno per ogni commit):
  • hai bisogno di un messaggio per lo scopo del rebase
  • git commit --allow-empty -m "empty"
  • avviare l'operazione di rebase
  • git rebase -i B^
  • B^ seleziona il genitore di B.
  • vorrai mettere un commit vuoto prima di ogni commit da modificare
  • vorrai cambiare pick in squash per quelli.

Esempio di cosa ti darà git rebase -i B^:

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

cambialo in:

# 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

Ti chiederà di modificare i messaggi:

# 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...

e puoi semplicemente rimuovere le prime righe.

Commentari (0)