Pytanie Jak zmienić nazwisko autora i zleceniodawcy oraz adres e-mail wielu zatwierdzeń w Git?


Pisałem prosty skrypt na szkolnym komputerze i wprowadzałem zmiany w Git (w repozytorium, które było w moim pendrive, sklonowanym z mojego komputera w domu). Po kilku zatwierdzeniach zdałem sobie sprawę, że popełniam błędy jako root.

Czy istnieje sposób na zmianę autora tych zmian na moje imię?


2004
2018-04-15 03:09


pochodzenie


Pytanie: czy przy użyciu gałęzi filtra GIT zachowujesz SHA1 dla poprzednich tagów, wersji i obiektów? Czy też zmiana siły nazwiska autora spowoduje zmianę skojarzonych SHA1? - AndyL
Hashe zmieni się tak - Not Available
Stycznie stworzyłem mały skrypt, który ostatecznie naprawił dla mnie podstawową przyczynę. gist.github.com/tripleee/16767aa4137706fd896c - tripleee
@impinball Wiek pytania nie ma większego znaczenia. Tworzenie nowego duplikatu pytania nie wchodzi w rachubę. Przypuszczam, że mógłbym stworzyć pytanie, które prosi o tę konkretną odpowiedź, ale nie jestem całkowicie przekonany, że uzyskałoby to tyle widoczności. To nie jest tak, że brakuje tu pytań Git ... Cieszę się, że i tak mogę pomóc. - tripleee
GitHub ma specjalny skrypt do tego: help.github.com/articles/changing-author-info - Timur Bernikowich


Odpowiedzi:


Zmiana autora (lub autora) wymagałaby ponownego napisania całej historii. Jeśli nie masz nic przeciwko temu i uważasz, że warto, to sprawdź git - gałąź filtru. Strona man zawiera kilka przykładów, od których możesz zacząć. Zwróć także uwagę, że możesz użyć zmiennych środowiskowych, aby zmienić nazwisko autora, autora, daty itd. - zobacz sekcję "Zmienne środowiskowe" Strona git man.

W szczególności możesz naprawić wszystkie złe nazwiska i adresy e-mail autora dla wszystkich gałęzi i tagów za pomocą tego polecenia (źródło: Pomoc GitHub):

#!/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

801
2018-04-15 03:16



Github ma do tego publiczny skrypt help.github.com/articles/changing-author-info i działa świetnie! - rodowi
Po wykonaniu skryptu możesz usunąć gałąź zapasową, wykonując polecenie "git update-ref -d refs / original / refs / heads / master". - D.R.
@rodowi, duplikuje wszystkie moje zatwierdzenia. - Rafael Barros
@RafaelBarros informacje o autorze (podobnie jak wszystko inne w historii) są częścią klucza sha zatwierdzenia. Każda zmiana w historii to przepisanie prowadzące do nowego identyfikatora dla wszystkich zatwierdzeń. Więc nie przepisuj ponownie na udostępnionym repo lub upewnij się, że wszyscy użytkownicy są tego świadomi ... - johannes
Rozwiązano za pomocą git push --force --tags origin HEAD:master - Matteo Contrini


Korzystanie z Interactive Rebase

Mógłbyś

git rebase -i -p <some HEAD before all of your bad commits>

Następnie oznacz wszystkie złe zatwierdzenia jako "edytuj" w pliku "rebase". Jeśli chcesz również zmienić swoje pierwsze zatwierdzenie, musisz ręcznie dodać je jako pierwszy wiersz w pliku rebase (postępuj zgodnie z formatem pozostałych linii). Następnie, gdy git prosi o zmianę każdego zatwierdzenia, zrób

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

edytuj lub po prostu zamknij edytor, który się otwiera, a następnie wykonaj

git rebase --continue

aby kontynuować odświeżanie.

Można pominąć tutaj otwarcie edytora przez dołączenie --no-edit aby polecenie brzmiało:

git commit --amend --author "New Author Name <email@address.com>" --no-edit && \
git rebase --continue

Pojedyncze zatwierdzenie

Jak zauważyli niektórzy komentatorzy, jeśli chcesz po prostu zmienić ostatnie zatwierdzenie, polecenie rebase nie jest konieczne. Po prostu zrób

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

Spowoduje to zmianę autora na wybraną nazwę, ale program zostanie skonfigurowany do skonfigurowanego użytkownika git config user.name i git config user.email. Jeśli chcesz ustawić committera na coś, co określisz, ustawi to zarówno autora, jak i autora:

 git -c user.name="New Author Name" -c user.email=email@address.com commit --amend --reset-author

Uwaga dotycząca scalania zatwierdzeń

W mojej pierwotnej odpowiedzi była niewielka wada. Jeśli są jakieś zatwierdzenia scalania między bieżącym HEAD I twój <some HEAD before all your bad commits>, następnie git rebase spłaszcza je (a przy okazji, jeśli użyjesz żądań ściągania GitHub, w twojej historii będzie mnóstwo potwierdzeń scalenia). Może to bardzo często prowadzić do bardzo odmiennej historii (ponieważ zduplikowane zmiany mogą być "ponownie rozliczane"), aw najgorszym przypadku może prowadzić do git rebase z prośbą o rozwiązanie trudnych konfliktów scalających (które prawdopodobnie zostały już rozwiązane w zatwierdzeniach scalania). Rozwiązaniem jest użycie -p flaga do git rebase, która zachowa strukturę scalania twojej historii. Strona podręcznika dla git rebase ostrzega, że ​​za pomocą -p i -i może prowadzić do problemów, ale w BUGS sekcja mówi "Edycja zatwierdzeń i przeformułowanie ich komunikatów zatwierdzania powinno działać dobrze."

dodałem -p do powyższego polecenia. W przypadku, gdy zmieniasz tylko ostatnie zatwierdzenie, nie stanowi to problemu.


1417
2017-08-24 03:08



Doskonały do ​​nieparzystego zatwierdzenia - przydatny, jeśli parujesz i zapomnisz zmienić autora - mloughran
+1 za wzmiankę o typowej naprawie jednego błędu: git commit --amend --author = nazwa użytkownika - Nathan Kidd
Jest to idealne, moim najczęstszym przypadkiem jest to, że siadam na innym komputerze i zapomniałem ustawić autora, a więc zazwyczaj ma się <5 zatwierdzeń lub coś takiego do naprawienia. - Zitrax
git commit --amend --reset-author działa również raz user.name i user.email są poprawnie skonfigurowane. - pts
Przepisz informacje o autorze po wszystkich zatwierdzeniach po <commit> za pomocą user.name i user.email od ~/.gitconfig: biegać git rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'Zapisz, wyjdź. Nie trzeba edytować! - ntc2


Możesz także:

git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

Uwaga: jeśli używasz tego polecenia w wierszu polecenia systemu Windows, musisz użyć "zamiast ':

git filter-branch --commit-filter "
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi" HEAD

566
2018-05-15 19:15



Czy korzystanie z filtra env nie jest prostszym rozwiązaniem? Nie wiesz, dlaczego to robi coraz więcej głosów. - stigkj
Następnie link jest zepsuty. W jaki sposób przenosimy te zmiany do innego repozytorium? - Russell
env-filter zmieni wszystkie zatwierdzenia. To rozwiązanie umożliwia warunkowe. - user208769
"A previous backup already exists in refs/original/ Force overwriting the backup with -f" przepraszam, ale gdzie -f -flag będzie wykonywał ten skrypt dwa razy. Właściwie to jest odpowiedź Briana, przepraszam za zakłócenie zaraz po rozwiązaniu filtra. - hhh
@ user208769 env-filter pozwala także na warunkowe; spójrz na moją odpowiedź :-) - stigkj


Jedna linijka, ale zachowaj ostrożność, jeśli masz repozytorium dla wielu użytkowników - to się zmieni wszystko zobowiązuje się do posiadania tego samego (nowego) autora i wspólnika.

git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='new@email'; GIT_COMMITTER_NAME='Newname'; GIT_COMMITTER_EMAIL='new@email';" HEAD

Z liniowymi rozbiciami w łańcuchu (co jest możliwe w bash):

git filter-branch -f --env-filter "
    GIT_AUTHOR_NAME='Newname'
    GIT_AUTHOR_EMAIL='new@email'
    GIT_COMMITTER_NAME='Newname'
    GIT_COMMITTER_EMAIL='new@email'
  " HEAD

483
2018-04-15 03:22



Tak, ale nie zapomnij nazwiska / adresu e-mail zleceniodawcy. To, co zadziałało, było dla mnie git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; GIT_COMMITER_NAME='Newname'; GIT_COMMITTER_EMAIL='newemail';" HEAD W przeciwnym razie git będzie śledził starą nazwę jako sprawca! - Olivier Verdier
@Olivier Masz literówkę na GIT_COMMITER_NAME -> GIT_COMMITTER_NAME - Filipe Correia
Działało dla mnie dla wszystkich zatwierdzeń, w tym dla pierwszego. - Vincent
Dlaczego przepisuje wszystkie zatwierdzenia, jeśli je określisz HEAD na końcu polecenia? - Nick Volynkin
To nie działa dla mojego repozytorium bitbucket, żadnego pomysłu? Robię git push --force --tags origin 'refs/heads/*' po poleconym dowództwie - ujsgeyrr1f0d0d0r0h1h0j0j_juj


Dzieje się tak, gdy nie zainicjowano programu $ HOME / .gitconfig. Możesz to naprawić jako:

git config --global user.name "you name"
git config --global user.email you@domain.com
git commit --amend --reset-author

przetestowane z wersją git 1.7.5.4


202
2018-02-16 09:46



Działa to bardzo dobrze przy ostatnim zatwierdzeniu. Ładne i proste. Nie robi mieć być globalną zmianą, używając --local działa też - Ben
git commit --amend --reset-author --no-edit - mafrosis


Dla pojedynczego zatwierdzenia:

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

(wyodrębniony z odpowiedzi udzielonej przez Asmeurer)


180
2018-04-26 22:50



ale to tylko wtedy, gdy jest to ostatnie zatwierdzenie - Richard
Według git help commit, git commit --amend zmienia zatwierdzenie na "końcu bieżącego oddziału" (czyli HEAD). Zazwyczaj jest to najnowszy commit, ale możesz go najpierw zatwierdzić Sprawdzać które popełniają z git checkout <branch-name> lub git checkout <commit-SHA>. - Rory O'Kane
Ale jeśli to zrobisz, wszystkie zatwierdzenia, które mają już zatwierdzenie jako rodzic, będą wskazywać na niewłaściwe zatwierdzenie. Lepiej używać w tym momencie gałęzi filtra. - John Gietzen
@JohnGietzen: Możesz ponownie umieścić commit na tym, który został zmieniony, aby to naprawić. Jeśli jednak robisz> 1 commit, to jak wspomniano, filtrowanie będzie prawdopodobnie łatwiejsze. - Thanatos
Zauważ, że to zmienia tylko zatwierdzenie author a nie committer - Nick Volynkin


W przypadku, gdy tylko kilka najlepszych commitów ma złych autorów, możesz to wszystko zrobić w środku git rebase -i używając exec polecenie i --amend zatwierdzić, jak następuje:

git rebase -i HEAD~6 # as required

który przedstawia edytowalną listę zatwierdzeń:

pick abcd Someone else's commit
pick defg my bad commit 1
pick 1234 my bad commit 2

Następnie dodaj exec ... --author="..." linie po wszystkich liniach ze złymi autorami:

pick abcd Someone else's commit
pick defg my bad commit 1
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD
pick 1234 my bad commit 2
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD

zapisz i wyjdź z edytora (aby uruchomić).

To rozwiązanie może być dłuższe niż niektóre inne, ale jest bardzo łatwe do kontrolowania - dokładnie wiem, co trafia.

Dzięki @emeurer za inspirację.


152
2017-12-08 17:05



Zdecydowanie niesamowite. Można go skrócić, ustawiając user.name i user.email w lokalnej konfiguracji repo, a następnie każda linia jest tylkoexec git commit --amend --reset-author -C HEAD ? - Andrew
@Andrew --reset-author działa dobrze. - Boggin
Odpowiedź kanoniczna, aby użyć filtra-gałęzi, właśnie usunęła dla mnie refs / heads / master. Dodaj +1 do kontrolowanego, edytowalnego rozwiązania. Dzięki! - jmtd
Dlaczego zaczynasz? Someone else's commitzamiast my bad commit 1? Właśnie próbowałem HEAD^^ zmienić ostatnie 2 zatwierdzenia i działało idealnie dobrze. - fredoverflow
Zamiast git rebase -i HEAD^^^^^^ możesz również pisać git rebase -i HEAD~6 - Patrick Schlüter


Github ma fajne rozwiązanie, który jest następującym skryptem powłoki:

#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ]
then
    cn="Your New Committer Name"
    cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ]
then
    an="Your New Author Name"
    am="Your New Author Email"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'

108
2017-10-07 09:54



Działa doskonale. Po prostu musiałem git reset --hard HEAD^ kilka razy w innych lokalnych repozytoriach, aby uzyskać je we wcześniejszej wersji, git pull-ed wersji poprawionej, i tutaj jestem bez żadnych linii zawierających unknown <stupid-windows-user@.StupidWindowsDomain.local>(polubił git's defaulting). - Alan Plum
Nie mogę naciskać po tym. Czy muszę używać "-f"? - fossilet
Zrobiłem git push -f. Ponadto, lokalne repo muszą zostać ponownie zaklasyfikowane po tym. - fossilet
Jeśli chcesz uruchomić skrypt powłoki w określonej gałęzi, możesz zmienić ostatnią linię na: "master-twoja-nazwa-nazwy" (zakładając, że masz rozgałęziony wzorzec). - Robert Kajic
Kliknij link <nice solution>, gdy skrypt został zaktualizowany - mdn


Jak wspomniano w dokumentach, przepisywanie historii jest niebezpieczne i łamie repozytoria innych osób.

Ale jeśli naprawdę chcesz to zrobić i jesteś w środowisku bash (nie ma problemu w Linuksie, w systemie Windows, możesz użyć git bash, który jest dostarczany z instalacją git), użyj git - gałąź filtru:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL'

Aby przyspieszyć działanie, możesz określić zakres wersji, które chcesz przepisać:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL' HEAD~20..HEAD

79
2017-08-04 00:52



Zwróć uwagę, że pozostawi to znaczniki wskazujące na stare zatwierdzenia. --tag-name-filter cat jest opcją "make it work". - Roman Starkov
@romkyns jakikolwiek pomysł na zmianę tagów? - Nick Volynkin
@NickVolynkin Tak, określasz --tag-name-filter cat. To powinno być domyślne zachowanie. - Roman Starkov