Pisałem prosty skrypt na szkolnym komputerze i zatwierdzałem zmiany w Git (w repozytorium, które było w moim pendrive, sklonowane z mojego komputera w domu). Po kilku zatwierdzeniach zdałem sobie sprawę, że popełniam rzeczy jako użytkownik root.
Czy jest jakiś sposób na zmianę autora tych zatwierdzeń na moje imię?
git
version-control
git-filter-branch
git-rewrite-history
Flávio Amieiro
źródło
źródło
Odpowiedzi:
Zmiana autora (lub autora) wymagałaby ponownego napisania całej historii. Jeśli nie masz nic przeciwko temu i uważasz, że warto, powinieneś sprawdzić git filter-branch . Strona podręcznika zawiera kilka przykładów na początek. Zauważ też, że możesz użyć zmiennych środowiskowych, aby zmienić nazwisko autora, autora, daty itp. - patrz sekcja „Zmienne środowiskowe” na stronie man git .
W szczególności za pomocą tego polecenia możesz naprawić wszystkie niepoprawne nazwy autorów i adresy e-mail dla wszystkich gałęzi i tagów (źródło: pomoc GitHub ):
źródło
git push --force --tags origin HEAD:master
UWAGA: Ta odpowiedź zmienia SHA1, więc uważaj, aby użyć jej na gałęzi, która została już wypchnięta. Jeśli chcesz tylko poprawić pisownię nazwy lub zaktualizować stary e-mail, git pozwala to zrobić bez przepisywania historii przy użyciu
.mailmap
. Zobacz moją drugą odpowiedź .Korzystanie z Interactive Rebase
Mógłbyś
Następnie zaznacz wszystkie swoje złe zmiany jako „edytuj” w pliku bazy danych. Jeśli chcesz również zmienić swoje pierwsze zatwierdzenie, musisz ręcznie dodać je jako pierwszą linię w pliku rebase (postępuj zgodnie z formatem pozostałych linii). Następnie, gdy git poprosi cię o zmianę każdego zatwierdzenia, zrób to
edytuj lub po prostu zamknij edytor, który się otworzy, a następnie zrób
aby kontynuować rebase.
Możesz pominąć otwarcie edytora tutaj, dodając,
--no-edit
aby polecenie było:Single Commit
Jak zauważyli niektórzy komentatorzy, jeśli chcesz tylko zmienić ostatnie zatwierdzenie, polecenie rebase nie jest konieczne. Po prostu zrób
Spowoduje to zmianę autora na podaną nazwę, ale podmiot ustawiający zostanie ustawiony na skonfigurowanego użytkownika w
git config user.name
igit config user.email
. Jeśli chcesz ustawić moduł ustalający na określony przez siebie element, spowoduje to ustawienie zarówno autora, jak i modułu zmieniającego:Uwaga dotycząca zatwierdzeń scalania
W mojej pierwotnej odpowiedzi była niewielka wada. Jeśli są jakieś zatwierdzenia scalania między bieżącym
HEAD
a twoim<some HEAD before all your bad commits>
, wówczasgit rebase
je spłaszczysz (a przy okazji, jeśli użyjesz żądań ściągania GitHub, w twojej historii będzie mnóstwo zatwierdzeń scalania). Może to często prowadzić do bardzo odmiennej historii (ponieważ duplikaty zmian mogą zostać „wycofane”), aw najgorszym przypadku mogą prowadzić dogit rebase
prośby o rozwiązanie trudnych konfliktów scalania (które prawdopodobnie zostały już rozwiązane w zatwierdzeniach scalania). Rozwiązaniem jest użycie-p
flagi dogit rebase
, która zachowa strukturę scalania twojej historii. Strona podręcznika dlagit rebase
ostrzega, że używanie-p
i-i
może prowadzić do problemów, ale wBUGS
w sekcji napisano: „Edytowanie zatwierdzeń i przeredagowanie ich komunikatów zatwierdzeń powinno działać dobrze”.Dodałem
-p
do powyższego polecenia. W przypadku, gdy zmieniasz tylko najnowsze zatwierdzenie, nie stanowi to problemu.źródło
git commit --amend --reset-author
działa również razuser.name
iuser.email
są poprawnie skonfigurowane.<commit>
użyciuuser.name
iuser.email
od~/.gitconfig
: uruchomgit rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'
, zapisz, wyjdź. Nie trzeba edytować!Możesz także:
Uwaga: jeśli używasz tego polecenia w wierszu polecenia systemu Windows, musisz użyć
"
zamiast'
:źródło
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"
przepraszam, ale gdzie-f
-flag będzie musiał wykonać ten skrypt dwa razy. Właściwie to jest odpowiedź Briana, przepraszam za zakłócenia zaraz po tym, jak odgałęzienie filtra jest rozwiązaniem.Jedna linijka, ale uważaj, jeśli masz repozytorium dla wielu użytkowników - spowoduje to zmianę wszystkich zatwierdzeń na tego samego (nowego) autora i osobę odpowiedzialną.
Z łamaniem wiersza w ciągu (co jest możliwe w bash):
źródło
HEAD
na końcu polecenia?git push --force --tags origin 'refs/heads/*'
po doradzał polecenia$git push --force --tags origin 'refs/heads/master'
Dzieje się tak, gdy nie masz zainicjowanego $ HOME / .gitconfig. Możesz to naprawić jako:
testowany z wersją git 1.7.5.4
źródło
--local
utworówgit commit --amend --reset-author --no-edit
Polecenia jest szczególnie przydatna, gdy tworzony zobowiązuje ze złym informacje o autorze, a następnie ustawić właściwy autor po-fakcie poprzezgit config
. Zapisałem moje $$ właśnie teraz, kiedy musiałem zaktualizować swój e-mail.Dla pojedynczego zatwierdzenia:
(wyodrębniony z odpowiedzi pośrednika)
źródło
git help commit
,git commit --amend
zmienia zatwierdzenie na „wierzchołku bieżącej gałęzi” (czyli HEAD). Zwykle jest to ostatni zatwierdzenie, ale możesz dokonać dowolnego zatwierdzenia, najpierw sprawdzając ten zatwierdzenie za pomocągit checkout <branch-name>
lubgit checkout <commit-SHA>
.author
a niecommitter
W przypadku, gdy tylko kilka pierwszych zatwierdzeń ma złych autorów, możesz to wszystko zrobić
git rebase -i
za pomocąexec
polecenia i--amend
zatwierdzenia, w następujący sposób:która przedstawia edytowalną listę zatwierdzeń:
Następnie dodaj
exec ... --author="..."
wiersze po wszystkich wierszach ze złymi autorami:zapisz i zamknij edytor (aby uruchomić).
To rozwiązanie może być dłuższe niż niektóre inne, ale można je w pełni kontrolować - wiem dokładnie, do czego się zobowiązuje.
Dzięki @asmeurer za inspirację.
źródło
exec git commit --amend --reset-author -C HEAD
?Someone else's commit
zamiastmy bad commit 1
? Właśnie próbowałemHEAD^^
zmienić ostatnie 2 zatwierdzenia i wszystko działało idealnie.git rebase -i HEAD^^^^^^
możesz także napisaćgit rebase -i HEAD~6
Github ma fajne rozwiązanie , którym jest następujący skrypt powłoki:
źródło
git reset --hard HEAD^
tylko kilka razy w innych lokalnych repozytoriach, aby przenieść je do wcześniejszej wersji,git pull
-ed poprawiona wersja, a tutaj nie mam żadnych wierszy zawierającychunknown <[email protected]>
(uwielbiam domyślną wersję gita).git push -f
. Ponadto lokalne repozytoria muszą zostać ponownie sklonowane.Jak wspomniano docgnome, przepisywanie historii jest niebezpieczne i spowoduje uszkodzenie repozytoriów innych ludzi.
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 filter-branch :
Aby przyspieszyć, możesz określić zakres poprawek, które chcesz przepisać:
źródło
--tag-name-filter cat
to opcja „spraw, by działała”.--tag-name-filter cat
. To naprawdę powinno być zachowanie domyślne.W przypadku przejęcia niezałączonego zatwierdzenia od innego autora istnieje prosty sposób na poradzenie sobie z tym.
git commit --amend --reset-author
źródło
--no-edit
aby było to jeszcze łatwiejsze, ponieważ generalnie większość ludzi będzie chciała zaktualizować tylko adres e-mail, a nie wiadomość zatwierdzeniaMożesz użyć tego jako aliasu, dzięki czemu możesz:
lub dla ostatnich 10 zatwierdzeń:
Dodaj do ~ / .gitconfig:
Źródło: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Mam nadzieję, że jest to przydatne.
źródło
To jest bardziej rozbudowana wersja wersji @ Briana:
Aby zmienić autora i committera, możesz to zrobić (z łamaniem linii w ciągu, co jest możliwe w bash):
Może pojawić się jeden z następujących błędów:
(oznacza to, że poprzednio uruchomiono inną gałąź filtrów w repozytorium, a następnie tworzona jest kopia zapasowa referencji oddziału w refs / original )
Jeśli chcesz wymusić uruchomienie pomimo tych błędów, dodaj
--force
flagę:-- --all
Może być potrzebne małe wyjaśnienie tej opcji: sprawia, że gałąź filtra działa we wszystkich wersjach we wszystkich referencjach (która obejmuje wszystkie gałęzie). Oznacza to na przykład, że tagi są również przepisywane i są widoczne na przepisanych gałęziach.Często stosuje się
HEAD
zamiast tego „błąd” , co oznacza filtrowanie wszystkich poprawek tylko w bieżącej gałęzi . I wtedy w przepisanej gałęzi nie istniałyby żadne tagi (ani inne referencje).źródło
Jedno polecenie , aby zmienić autora z ostatnich N zobowiązuje:
UWAGI
--no-edit
odbierają fladze, czygit commit --amend
nie poprosić o dodatkowe potwierdzeniegit rebase -i
, możesz ręcznie wybrać zatwierdzenia, gdzie zmienić autora,plik, który edytujesz, będzie wyglądał tak:
Następnie możesz nadal modyfikować niektóre wiersze, aby zobaczyć, gdzie chcesz zmienić autora. Daje to przyjemny pośrednik między automatyzacją a kontrolą: widzisz kroki, które zostaną wykonane, a po zapisaniu wszystko zostanie zastosowane na raz.
źródło
git rebase -i master -x ...
git rebase -i <sha1 or ref of starting point>
edit
(lube
)zapętlaj następujące dwa polecenia, aż przetworzysz wszystkie zatwierdzenia:
git commit --amend --reuse-message=HEAD --author="New Author <[email protected]>"
;git rebase --continue
Pozwoli to zachować wszystkie inne informacje dotyczące zatwierdzeń (w tym daty). Ta
--reuse-message=HEAD
opcja zapobiega uruchomieniu edytora wiadomości.źródło
Używam następujących poleceń do przepisania autora dla całego repozytorium, w tym znaczników i wszystkich gałęzi:
Następnie, jak opisano na stronie MAN gałęzi filter- , usuń wszystkie oryginalne referencje, których kopie zapasowe utworzono
filter-branch
(destrukcyjne, najpierw wykonaj kopię zapasową):źródło
--tag-name-filter cat
. W przeciwnym razie tagi pozostaną w oryginalnym łańcuchu zatwierdzeń. Inne odpowiedzi nie wspominają o tym.Zaadaptowałem to rozwiązanie, które działa poprzez przyjęcie prostego
author-conv-file
(format jest taki sam jak dla git-cvsimport ). Działa poprzez zmianę wszystkich użytkowników zgodnie z definicją wauthor-conv-file
we wszystkich gałęziach.Użyliśmy tego w połączeniu z
cvs2git
do migracji naszego repozytorium z cvs do git.tj. próbka
author-conv-file
Scenariusz:
źródło
Powinienem zauważyć, że jeśli jedynym problemem jest to, że autor / adres e-mail różni się od zwykłego, nie stanowi to problemu. Poprawną poprawką jest utworzenie pliku o nazwie
.mailmap
u podstawy katalogu z liniami podobnymiI odtąd polecenia takie
git shortlog
uznają te dwie nazwy za takie same (chyba, że wyraźnie im to powiesz). Więcej informacji można znaleźć na stronie http://schacon.github.com/git/git-shortlog.html .Ma to tę zaletę, że nie wymaga przepisywania historii, co może powodować problemy w przypadku przesyłania danych i zawsze jest dobrym sposobem na przypadkową utratę danych.
Oczywiście, jeśli popełniłeś coś jak ty i naprawdę powinien to być ktoś inny, i nie masz nic przeciwko przepisywaniu historii w tym momencie, zmiana autora zatwierdzenia jest prawdopodobnie dobrym pomysłem do celów przypisania (w takim przypadku kieruję cię do mojego inna odpowiedź tutaj).
źródło
Znalazłem prezentowane wersje jako zbyt agresywne, szczególnie jeśli popełnisz łatki od innych programistów, to w zasadzie wykradnie ich kod.
Poniższa wersja działa we wszystkich gałęziach i zmienia osobno autora i autora, aby temu zapobiec.
Wyrazy uznania dla leif81 dla wszystkich opcji.
źródło
Zmień zatwierdzenie
author name & email
przezAmend
, a następnie zastępującold-commit with new-one
:Inny sposób
Rebasing
:źródło
Najszybszym i najłatwiejszym sposobem na to jest użycie argumentu --exec git rebase:
Spowoduje to utworzenie listy rzeczy do zrobienia, która wygląda następująco:
i to zadziała automatycznie, co działa, gdy masz setki zatwierdzeń.
źródło
Jeśli jesteś jedynym użytkownikiem tego repozytorium, możesz przepisać historię za pomocą
git filter-branch
(jak napisał svick ) lubgit fast-export
/git fast-import
i skryptu filtrującego (zgodnie z opisem w artykule, do którego odwołuje się odpowiedź docgnome ) lub interaktywnego rebase . Ale którykolwiek z nich zmieniłby poprawki od pierwszej zmiany zatwierdzenia; oznacza to kłopoty dla każdego, kto oparł swoje zmiany na przepisaniu twojego oddziału.POPRAWA
Jeśli inni programiści nie oparli swojej pracy na wersji przed przepisaniem, najprostszym rozwiązaniem byłoby ponowne sklonowanie (ponowne sklonowanie).
Ewentualnie mogą spróbować
git rebase --pull
, który przewinąłby do przodu, gdyby nie było żadnych zmian w ich repozytorium, lub zmienił ich oddział na podstawie ponownie zapisanych zatwierdzeń (chcemy uniknąć scalania, ponieważ zachowałoby wcześniejsze zapisywanie zmian na zawsze). Wszystko to przy założeniu, że nie zobowiązali się do pracy; posługiwać sięgit stash
aby w inny sposób ukryć zmiany.Jeśli inni programiści używają gałęzi funkcji i / lub
git pull --rebase
nie działają, np. Ponieważ upstream nie jest skonfigurowany, muszą bazować swoją pracę na zatwierdzonych zmianach. Na przykład tuż po pobraniu nowych zmian (git fetch
), dlamaster
gałęzi opartej na / forked fromorigin/master
, należy uruchomićOto
origin/master@{1}
stan przed przepisaniem (przed pobraniem ), zobacz gitrevisions .Alternatywnym rozwiązaniem byłoby użycie referencji / zamiany / mechanizmu, dostępnych w Git od wersji 1.6.5. W tym rozwiązaniu zapewniasz zamienniki dla zatwierdzeń, które mają błędny adres e-mail; wtedy każdy, kto pobierze „zamień” referencje (coś w rodzaju
fetch = +refs/replace/*:refs/replace/*
referencje refspec w odpowiednim miejscu w ich miejscu.git/config
) otrzyma zamiany w sposób przejrzysty, a ci, którzy nie zobaczą stare zatwierdzenia.Procedura przebiega mniej więcej tak:
Znajdź wszystkie zatwierdzenia z niewłaściwym adresem e-mail, na przykład używając
Dla każdego niepoprawnego zatwierdzenia utwórz zatwierdzenie zastępcze i dodaj je do bazy danych obiektów
Teraz, gdy poprawiłeś zatwierdzenie w bazie danych obiektów, musisz powiedzieć gitowi, aby automatycznie i przejrzyście zamieniał niepoprawne zatwierdzenie przez poprawienie jednego za pomocą
git replace
polecenia:Na koniec wypisz listę wszystkich zamienników, aby sprawdzić, czy procedura się powiodła
i sprawdź, czy nastąpi wymiana
Możesz oczywiście zautomatyzować tę procedurę ... cóż, wszystko oprócz użycia
git replace
który nie ma (jeszcze) trybu wsadowego, więc musiałbyś do tego użyć pętli powłoki lub zastąpić ją „ręcznie”.NIE TESTOWANY!YMMV.
Pamiętaj, że podczas korzystania z
refs/replace/
mechanizmu możesz napotkać pewne nierówne kąty : jest nowy i jeszcze nie bardzo dobrze przetestowany .źródło
Jeśli zatwierdzenia, które chcesz naprawić, są najnowsze, a tylko kilka z nich, możesz użyć kombinacji
git reset
igit stash
aby wrócić i zatwierdzić je ponownie po skonfigurowaniu prawidłowej nazwy i adresu e-mail.Sekwencja będzie mniej więcej taka (dla 2 błędnych zatwierdzeń, bez oczekujących zmian):
źródło
Jeśli używasz Eclipse z EGit, istnieje całkiem proste rozwiązanie.
Założenie: masz zatwierdzenia w lokalnym oddziale „local_master_user_x”, którego nie można przekazać do zdalnego oddziału „master” z powodu nieprawidłowego użytkownika.
źródło
Korzystając z interaktywnej bazy danych, możesz umieścić polecenie zmiany po każdym zatwierdzeniu, które chcesz zmienić. Na przykład:
źródło
;-)
.Należy pamiętać, że sklepy git dwa różne adresy e-mail, jeden dla committer (osoba, która dopuściła się zmiany) i drugi dla autora (osoby, która napisała zmiany).
Informacje o committerze nie są wyświetlane w większości miejsc, ale można je zobaczyć za pomocą
git log -1 --format=%cn,%ce
(lub użyćshow
zamiast,log
aby określić konkretne zatwierdzenie).Chociaż zmiana autora ostatniego zatwierdzenia jest tak prosta
git commit --amend --author "Author Name <[email protected]>"
, że nie ma jednego wiersza ani argumentu, który mógłby zrobić to samo z informacjami o komisarzu.Rozwiązaniem jest (tymczasowo lub nie) zmiana informacji o użytkowniku, a następnie zmiana zatwierdzenia, która zaktualizuje podmiot zatwierdzający do bieżących informacji:
źródło
path\to\repo\.git
. Nie jestem jeszcze pewien, co musisz zrobić, aby całkowicie to zniszczyć. Poprawki niestety (?) Nie usuwają się.Wystąpił dzisiaj problem, w wyniku którego znak UTF8 w nazwie autora powodował problemy na serwerze kompilacji, więc musieliśmy przepisać historię, aby to naprawić. Podjęte kroki to:
Krok 1: Zmień swoją nazwę użytkownika w git dla wszystkich przyszłych zatwierdzeń, zgodnie z instrukcjami tutaj: https://help.github.com/articles/setting-your-username-in-git/
Krok 2: Uruchom następujący skrypt bash:
Szybki przegląd: Pobierz repozytorium do pliku tymczasowego, sprawdź wszystkie zdalne gałęzie, uruchom skrypt, który przepisuje historię, wymuś nowy stan i powiedz wszystkim swoim kolegom, aby wykonali rebase, aby uzyskać zmiany.
Mieliśmy problem z uruchomieniem tego w systemie OS X, ponieważ w jakiś sposób pomieszało się ono z zakończeniami linii w komunikatach zatwierdzania, dlatego musieliśmy ponownie uruchomić go na komputerze z systemem Linux.
źródło
Twój problem jest naprawdę powszechny. Zobacz „ Korzystanie z Mailmap do naprawy listy autorów w Git ”
Dla uproszczenia stworzyłem skrypt ułatwiający proces: git-changemail
Po umieszczeniu tego skryptu na swojej ścieżce możesz wydawać polecenia takie jak:
Zmień dopasowania autora w bieżącym oddziale
Zmień dopasowania autora i committera w <branch> i <branch2>. Przekaż
-f
do gałęzi filter, aby umożliwić przepisywanie kopii zapasowychPokaż istniejących użytkowników na repo
Nawiasem mówiąc, po dokonaniu zmian wyczyść kopię zapasową z gałęzi filtru za pomocą: git-backup-clean
źródło
Wypróbuj to. Będzie działał tak samo jak wyżej wspomniany, ale interaktywnie.
Odniesienie: https://github.com/majdarbash/git-author-change-script
źródło
Chcę też dodać mój przykład. Chcę utworzyć funkcję bash z podanym parametrem.
działa to w wersji mint-linux-17.3
źródło
Jeśli jesteś jedynym użytkownikiem tego repozytorium lub nie obchodzi Cię ewentualne uszkodzenie repozytorium dla innych użytkowników, to tak. Jeśli wypchnąłeś te zatwierdzenia i istnieją one tam, gdzie gdzie indziej mają do nich dostęp, to nie, chyba że nie przejmujesz się łamaniem repozytoriów innych ludzi. Problem polega na tym, że zmieniając te zatwierdzenia, będziesz generować nowe SHA, co spowoduje, że będą traktowane jak różne zatwierdzenia. Kiedy ktoś próbuje wciągnąć te zmienione zobowiązania, historia jest inna i kaboom.
Ta strona http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html opisuje, jak to zrobić. (Nie próbowałem tego, więc YMMV)
źródło
refs/replace/
mechanizm.