Jak edytować historię gita, aby poprawić niepoprawny adres e-mail / nazwę [zamknięte]

76

Kiedy zacząłem używać git, właśnie zrobiłem a git initi zacząłem dzwonić addi commit. Teraz zaczynam zwracać uwagę i widzę, że moje zobowiązania są wyświetlane jako cowens@localmachine, a nie adres, który chcę. Wygląda na to, że ustawiam GIT_AUTHOR_EMAILi GIT_COMMITTER_EMAILzrobię to, co chcę, ale wciąż mam te stare zatwierdzenia z niewłaściwym adresem / nazwą e-mail. Jak mogę poprawić stare zatwierdzenia?

Chas. Owens
źródło
4
Dla naszych przyszłych czytelników: pytania dotyczące używania gitdo celów podobnych do tego lepiej zadaje się w przypadku przepełnienia stosu .
Michael Hampton
Oto najbliższe pytanie na stackoverflow.com.
naught101

Odpowiedzi:

82

Możesz wrócić i naprawić wszystkie swoje zobowiązania za pomocą pojedynczego połączenia z git filter-branch. Ma to taki sam efekt jak rebase, ale wystarczy wykonać jedno polecenie, aby naprawić całą historię, zamiast naprawiać każde zatwierdzenie osobno.

Za pomocą tego polecenia możesz naprawić wszystkie błędne wiadomości e-mail:

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

Więcej informacji jest dostępnych w Git Docs

andy
źródło
11
cóż, git filter-branch - env-filter 'export GIT_AUTHOR_EMAIL = "[email protected]"; GIT_AUTHOR_NAME = "Foo"' jest o wiele prostszy, dzięki. To byłaby zaakceptowana odpowiedź, gdybym mógł ją zmienić (wygląda na to, że wystąpił błąd z błędem serwera).
Chas. Owens
7
Zauważ, że linie eksportu NIE powinny mieć spacji po obu stronach znaku równości. Tzn. Powinny wyglądać tak: export GIT_AUTHOR_EMAIL = "(poprawny e-mail)";
Andy Balaam
1
Jak mam to zrobić w systemie Windows?
Carsten Schmitz,
2
@Deckard: zapisz skrypt w pliku tekstowym, takim jak fixcommits.sh, a następnie uruchom Git Bash i uruchom skrypt. Umieściłem plik skryptu w katalogu głównym mojego repozytorium, następnie przeszedłem do tego folderu w Git Bash, a następnie uruchomiłem skrypt z ./fixcommits.sh
Avalanchis
2
Dodatek 1 Ten format poleceń nie działał dla mnie, ale jeśli / to zrobił:if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
Josh M.
28

Polecenie Git filter-branch jest potężne, ale strasznie niewygodne jest używanie go do wszystkiego, co nie jest trywialne, na przykład, jeśli masz więcej niż jednego autora do poprawienia.

Oto alternatywa, którą uważam za przydatną, która wykorzystuje funkcję .mailmap opisaną na stronie podręcznika git-shortlog. Zapewnia to mechanizm mapowania autora, którego możemy używać z narzędziem formatującym git log. Możemy go użyć do wygenerowania poleceń do wybierania i poprawiania nazwanej sekwencji zatwierdzeń.

Załóżmy na przykład, że chcesz poprawić autorstwo w oddziale $ BRANCH, zaczynając od zatwierdzenia $ START.

Musisz utworzyć plik .mailmap w górnym katalogu swojego repozytorium, który mapuje istniejące nazwiska autorów na poprawne. Możesz uzyskać listę istniejących nazwisk autorów za pomocą:

git shortlog -se

Musisz skończyć z plikiem .mailmap takim jak ten (powiedzmy):

You <[email protected]>   cowens@localmachine
You <[email protected]>   root@localmachine

Teraz możesz użyć funkcji formatowania dziennika git, aby wygenerować polecenia przepisania $ BRANCH na $ BRANCH2.

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

Pierwsze polecenie tworzy nową pustą gałąź wyrastającą z zatwierdzenia $ START. Dla każdego zatwierdzenia między $ START a potem końcem $ BRANCH, drugie polecenie cherry wybiera oryginalne zatwierdzenie na końcu bieżącej gałęzi $ BRANCH2 i poprawia je, aby poprawnie ustawić autora.

Ma to również ogólne zastosowanie - umieść to w swoim ~ / .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" '

Więc kiedy musisz poprawić autorów, teraz musisz wygenerować plik .map i wykonać:

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

Pierwotny numer referencyjny oddziału można przypisać do nowego, a nowy usunąć:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
Wu-Lee
źródło
To jest niesamowite. Nagrodzę cię, gdybym miał więcej przedstawicieli. Dzięki :)
pistache 10.12
9

Łączenie odpowiedzi z Jak naprawić metainformację przy pierwszym zatwierdzeniu w 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 [email protected]"
# (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 [email protected]"
# (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
Chas. Owens
źródło
Doprowadził mnie do właściwego toru, ale potrzebowałem polecenia z: stackoverflow.com/a/28536828/307 zamiast --autoryzacja
Brett Veenstra
5

Aby podążać za odpowiedzią Jedberga: Możesz użyć rebase -ii wybrać edycję przedmiotowych zatwierdzeń. Jeśli używasz, git commit --amend --author <AUTHOR DETAILS>a następnie git rebase continuemożesz przejść i naprawić historię.

Chealion
źródło