Edytować zatwierdzenie roota w Git?

328

Istnieją sposoby zmiany wiadomości z późniejszych zatwierdzeń:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

Jak możesz zmienić komunikat zatwierdzenia pierwszego zatwierdzenia (który nie ma rodzica)?

13ren
źródło
W szczególności: użycie zmiennej środowiskowej GIT_COMMIT w skrypciegit filter-branch --msg-filter
fork0
1
patrz także stackoverflow.com/a/2309391/264607
BlackICE

Odpowiedzi:

285

Zakładając, że masz czyste drzewo robocze, możesz wykonać następujące czynności.

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master
CB Bailey
źródło
23
Wierzę, że tak powinno być git rebase --onto HEAD <sha1-of-root> master.
Andrew
5
Zgadza się, ale chcesz oryginalnego zatwierdzenia głównego dla <upstream> z git rebase. git rebasestosuje zatwierdzenia w <branch> ( master), które nie są w <upstream>; HEADnie ma master, więc Twoja wersja próbuje zastosować wszystkie master.
Andrew
7
Tak, upewnij się, że jest to git rebase --onto HEAD <sha1-of-root>master, gdzie <sha1-of-root>jest to samo, co używane git checkout <sha1-of-root>. W przeciwnym razie będziesz mieć 2 first commit.
Andy
2
@Ciastko: Czy przetestowałeś starą wersję polecenia? Powinno działać dobrze. Poprawka zmienia komunikat zatwierdzenia tylko po to, aby stare i nowe zatwierdzenia roota wprowadziły dokładnie te same zmiany, dzięki czemu stare zatwierdzenie root zostanie automatycznie pominięte. Drugi HEADzapewnia, że ​​wszystkie zatwierdzenia są brane pod uwagę i że możemy użyć dwuparametrowej wersji rebase, aby przejść z powrotem na master. Pamiętaj, że ta odpowiedź poprzedza istnienie --rootopcji rebase.
CB Bailey,
9
Odpowiedź ecdpalmy poniżej jest znacznie łatwiejsza i prostsza i ma więcej głosów, przewiń w dół ludzi!
Flimm,
567

Od wersji Git 1.7.12 możesz teraz używać

git rebase -i --root

Dokumentacja

ecdpalma
źródło
2
czy można zmienić bazę wszystkich gałęzi za pomocą tego polecenia? Wygląda na to, że odłączy bieżącą gałąź do nowego katalogu głównego, a wszystkie pozostałe gałęzie pozostaną na starym katalogu głównym
woojoo666,
@ woojoo666 będziesz musiał wtedy dokonać podziału bazy na nowy katalog główny. jak zwykle.
berkus
@Atcold to nie działa, jeśli nie ma głównego katalogu głównego
Kai
Ostrzeżenie: błędnie założyłem, że spowoduje to zrobienie katalogu głównego mojej wyewidencjonowanej gałęzi, ale ładowanie wszystkich zatwierdzeń zajmuje trochę czasu, a następnie ponowne ich rozłożenie.
Leo
2
@Leo co oznacza twój komentarz? Nie widzę związku między pierwszą częścią a drugą - co to ma z tym wspólnego?
boycy
66

Aby rozwinąć odpowiedź ecdpalmy , możesz teraz użyć --rootopcji, aby powiedzieć rebase, że chcesz przepisać root / first commit:

git rebase --interactive --root

Następnie zatwierdzenie główne pojawi się na liście DO ZROBIENIA w bazie danych i możesz go edytować lub przeredagować:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

Oto wyjaśnienie --rootz dokumentacji Git rebase (moje podkreślenie):

Rebase wszystkie zatwierdzenia dostępne z <branch>, zamiast ograniczać je za pomocą <upstream>.To pozwala na zmianę podstawowych zatwierdzeń w gałęzi .

Społeczność
źródło
12

Aby zapewnić alternatywę dla wyżej ocenianych odpowiedzi:

Jeśli tworzysz repozytorium i wiesz z góry, że będziesz opierać się na jego „pierwszym” prawdziwym zatwierdzeniu w przyszłości, możesz całkowicie uniknąć tego problemu, tworząc wyraźne puste zatwierdzenie na początku:

git commit --allow-empty -m "Initial commit"

i dopiero wtedy zacznij robić „prawdziwe” zatwierdzenia. Następnie, na przykład, możesz łatwo zmienić bazę na standardowe zatwierdzeniegit rebase -i HEAD^

jakub.g
źródło
4
Czy to nie znaczy, że aby to zadziałało, musisz mieć dalekowzroczność (lub być wścibski), aby dokonać pustego zatwierdzenia na samym początku swojego projektu ? Wydaje mi się to bardzo sytuacyjne i ogólnie niepraktyczne . Co myślisz? Co się stanie, jeśli już wykonałem 100 zatwierdzeń i nagle muszę edytować zatwierdzenie główne. Czy to nadal będzie działać, jeśli nie wprowadzę tego pustego zatwierdzenia na początku?
2
Edycja komunikatu głównego zatwierdzenia prawdopodobnie nie jest czymś, co zrobiłbyś po ich setkach. Czasami po prostu chcę mieć repozytorium git, wykonując tandetne zmiany, wiedząc, że kiedy osiągnę jakiś użyteczny stan, zmiażdżę je na przykład i przeredaguję wiadomość. W każdym razie, teraz zmieniłem zdanie i myślę, że absolutnie najbardziej użyteczną rzeczą dla pierwszego zatwierdzenia byłoby umieszczenie .gitattributespliku zamiast wykonania pustego zatwierdzenia.
jakub.g
4

Możesz użyć git filter-branch:

cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit
Alexander Groß
źródło
Korzystam z zmiany gałęzi filtru autor / committer, a -- --allopcja rzeczywiście jest kluczem w tym przypadku, aby móc również obsługiwać rootowanie.
sschuberth