Jak edytować niepoprawny komunikat o zatwierdzeniu w git (który przesłałem)?

152

Chcę zmodyfikować komunikat o zmianach głębiej w historii i wypchnąłem wiele nowych zatwierdzeń.

Jak zmienić wiadomość dotyczącą zatwierdzenia? Czy to możliwe?

Mehdi Raash
źródło

Odpowiedzi:

125

Wiadomość od Linusa Torvaldsa może odpowiedzieć na Twoje pytanie:

Zmodyfikuj / edytuj stare komunikaty o zatwierdzeniach

Krótka odpowiedź: nie możesz (jeśli jest popchnięty).


ekstrakt (Linus odnosi się do BitKeepera jako BK):

Na marginesie, tylko ze względów historycznych: w BK można.

A jeśli byłeś do tego przyzwyczajony (tak jak ja), było to bardzo praktyczne. Zastosowałbym bombę łatkową od Andrew, zauważyłem, że coś jest nie tak i po prostu wyedytowałem to przed wypchnięciem.

Mogłem zrobić to samo z git. Byłoby dość łatwo, gdyby tylko komunikat o zatwierdzeniu nie był częścią nazwy, a mimo to gwarantował, że historia pozostała nietknięta, i pozwolił na „późniejsze naprawienie komentarzy”.

Ale tego nie zrobiłem.

Po części jest to czysto „wewnętrzna spójność”. Git jest po prostu czystszym systemem dzięki temu, że wszystko jest chronione SHA1, a wszystkie obiekty są traktowane tak samo, niezależnie od typu obiektu. Tak, istnieją cztery różne rodzaje obiektów i wszystkie są naprawdę różne i nie można ich używać w ten sam sposób, ale w tym samym czasie, nawet jeśli ich kodowanie może być inne na dysku, koncepcyjnie wszystkie działają dokładnie to samo.

Jednak wewnętrzna spójność nie jest tak naprawdę wymówką dla bycia nieelastycznym i oczywiście byłoby bardzo elastyczne, gdybyśmy mogli po prostu naprawić błędy po ich wystąpieniu. Więc to nie jest naprawdę mocny argument.

Prawdziwy powód git nie pozwalają na zmianę zatwierdzenia końce wiadomość UP jest bardzo prosta: w ten sposób można zaufać wiadomości. Jeśli później pozwoliłeś ludziom je zmieniać, wiadomości z natury nie są zbyt godne zaufania.


Aby być kompletny, to mógłby przepisać z lokalnym popełnienia historii, aby odzwierciedlić to, co chcesz, jak sugeruje Sykora (z pewnym rebase i zresetować --hard, ciężko oddychać!)

Jednak po opublikowaniu poprawioną historią ponownie (z git push origin +master:masterThe +znak zmuszając push występuje, nawet jeśli to nie skutkuje w „fast-forward” commit) ... ty może dostać się w kłopoty .

Wyciąg z tego innego pytania SO:

Właściwie raz przepchnąłem się z --force do repozytorium git.git i zostałem zbesztany przez Linusa BIG TIME. Stworzy to wiele problemów innym ludziom. Prosta odpowiedź brzmi „nie rób tego”.

VonC
źródło
dobra odpowiedź. Czy wiesz, czy możesz teraz zmienić już wypchnięte komunikaty o zatwierdzeniach w nowszych wersjach gita? Czy coś się zmieniło od czasu opublikowania tego w '09?
David West
@DavidWest obowiązuje ta sama zasada: możesz przepisać swoją historię i wymusić pchnięcie.
VonC,
2
Aby uczynić rzeczy bardziej szczegółowymi, jeśli poprawisz / zmienisz bazę zatwierdzeń, ich identyfikatory zatwierdzeń (szesnastkowe skróty w indeksie git) nieuchronnie się zmienią; oznacza to, że edytowane zatwierdzenia są traktowane inaczej niż ich stare zatwierdzenia w historii git VCS. To powiedziawszy, jeśli członkowie twojego zespołu deweloperskiego niestety już wyciągnęli stare zatwierdzenia, są zobowiązani do ściągnięcia edytowanych, nowych zatwierdzeń i wykonania scalenia starego i nowego w swoich lokalnych kopiach roboczych.
Shigerello
1
Lepiej jest wypychać edytowane zatwierdzenia od nowa dla wygody współpracowników, co korzystnie eliminuje potrzebę scalania kopii roboczych kolegów.
Shigerello
28

Obecnie zastąpienie gita może załatwić sprawę.

Szczegóły: Utwórz tymczasową gałąź pracy

git checkout -b temp

Przywróć zobowiązanie do zastąpienia

git reset --hard <sha1>

Zmień zmianę, dodając odpowiednią wiadomość

git commit --amend -m "<right message>"

Zastąp stary commit nowym

git replace <old commit sha1> <new commit sha1>

wróć do oddziału, w którym byłeś

git checkout <branch>

usuń gałąź tymczasową

git branch -D temp

Pchać

guess

Gotowe.

Johan
źródło
11
@Jonah: Otrzymuję wiadomość „Wszystko jest aktualne”, kiedy próbuję
przesłać dane
1
Jak wspomniano w innej odpowiedzi: użyj rebase -i z reword. I zmieni historię.
Sylvain
Dziękuję za rozwiązanie, którego szukałem. Oszczędzasz mój czas!
Tomasz Kuter
1
@Jonah - mam problem ... Twoje rozwiązanie zaktualizowało moje dzienniki zatwierdzeń lokalnie, ale nie zdalnie. Jak je tam popchnąć?
Tomasz Kuter
1
@TomaszKuter, miałem ten sam problem co Ty. Moja wiadomość dotycząca zatwierdzenia nie została zdalnie zaktualizowana. Rozwiązałem to, korzystając z pomocy z GitHub: help.github.com/articles/changing-a-commit-message . Postępuj zgodnie z sekcją: Zmiana wiadomości starszych lub wielokrotnych komunikatów o zatwierdzeniach. Jest to w zasadzie odpowiedź podana poniżej przez użytkownika987419. Jeśli już zmieniłeś komunikat o zatwierdzeniu, możesz wybrać i zapisać bez konieczności ponownej zmiany.
evaldeslacasa
19

Możesz użyć git rebase -i(w stosunku do gałęzi, z której się rozgałęziłeś) „i” do interakcji.

Zastąp picknastępny komentarz do zatwierdzenia, który chcesz zmienić, r(lub reword), zapisz i zakończ, a po wykonaniu tej czynności będziesz mógł dokonać edycji.

git push jeszcze raz i gotowe!

Marcus
źródło
1
To nie pozwala na edycję wiadomości przy zatwierdzeniach scalających. Czy to możliwe z jakimś wariantem tego polecenia?
Andrew Mao
1
Spróbuj -pargumentu, rebasektóry prezerwy łączy.
Cactus
3
Podoba mi się ta procedura, ale na początku nie do końca rozumiałem odpowiedź. W przypadku, gdy ktoś potrzebuje pomocy, strona pomocy Githulb oferuje dobre informacje na ten temat: help.github.com/articles/changing-a-commit-message
evaldeslacasa
15

Załóżmy, że masz takie drzewo:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]

Najpierw checkoutgałąź tymczasowa:

git checkout -b temp

W tempgałęzi, reset --harddo zatwierdzenia, którego treść chcesz zmienić (na przykład, zatwierdzenie to 946992):

git reset --hard 946992

Użyj, amendaby zmienić wiadomość:

git commit --amend -m "<new_message>"

Po tym drzewo będzie wyglądać następująco:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
           \
            b886a0 [temp]

Następnie cherry-pickwszystkie zatwierdzenie, które wyprzedza 946992od masterdo tempi zatwierdza je, użyj, amendjeśli chcesz również zmienić ich komunikaty:

git cherry-pick 9143a9
git commit --amend -m "<new_message>
...
git cherry-pick 5a6057
git commit --amend -m "<new_message>

Drzewo wygląda teraz następująco:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
               \
                b886a0 - 41ab2c - 6c2a3s - 7c88c9 [temp]

Teraz wymuś wypchnięcie gałęzi temp do zdalnego:

git push --force origin temp:master

Ostatni krok, usuń gałąź masterlokalną, git fetch originaby pobrać gałąź masterz serwera, a następnie przełącz się na gałąź masteri usuń gałąź temp.

Teraz zarówno twój lokalny, jak i zdalny będą mieć zaktualizowane wszystkie wiadomości.

Huy Vo
źródło
5

W naszym sklepie wprowadziłem konwencję dodawania rozpoznawalnie nazwanych tagów z adnotacjami do zatwierdzeń z niepoprawnymi wiadomościami i używania adnotacji jako zamiennika.

Mimo że nie pomaga to ludziom, którzy uruchamiają zwykłe polecenia „git log”, zapewnia nam sposób na naprawienie nieprawidłowych odniesień do śledzenia błędów w komentarzach, a wszystkie moje narzędzia do kompilacji i wydania rozumieją konwencję.

Oczywiście nie jest to ogólna odpowiedź, ale może to być coś, co ludzie mogą zastosować w określonych społecznościach. Jestem pewien, że jeśli zostanie użyty na większą skalę, może pojawić się jakiś rodzaj porcelanowego podłoża, w końcu ...

Christian Goetze
źródło
3
„git notes” może służyć podobnemu celowi
Christian Goetze
2

(Z http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0 )

Jak zmienić zobowiązania głębiej w historii

Ponieważ historia w Git jest niezmienna, naprawienie czegokolwiek poza najnowszym zatwierdzeniem (zatwierdzeniem, które nie jest nagłówkiem gałęzi) wymaga przepisania historii ze zmienionego zatwierdzenia i do przodu.

Możesz użyć do tego StGIT, zainicjować gałąź, jeśli to konieczne, cofnąć zatwierdzenie do zatwierdzenia, które chcesz zmienić, pop do niego, jeśli to konieczne, dokonać zmiany, a następnie odświeżyć łatkę (z opcją -e, jeśli chcesz poprawić komunikat o zatwierdzeniu), a następnie wciśnij wszystko i zobowiązanie stg.

Możesz też użyć do tego rebase. Utwórz nową tymczasową gałąź, przewiń ją do zatwierdzenia, który chcesz zmienić, używając git reset --hard, zmień to zatwierdzenie (będzie to początek aktualnej głowy), a następnie ponownie wykonaj gałąź na podstawie zmienionego zatwierdzenia, używając git rebase --onto.

Lub możesz użyć git rebase --interactive, który umożliwia różne modyfikacje, takie jak zmiana kolejności poprawek, zwijanie, ...

Myślę, że to powinno odpowiedzieć na twoje pytanie. Należy jednak pamiętać, że jeśli wypchnąłeś kod do zdalnego repozytorium i ludzie z niego wyciągnęli, to zepsuje to ich historię kodu, a także pracę, którą wykonali. Więc rób to ostrożnie.

sykora
źródło
Dobra odpowiedź w teorii, bardzo niebezpieczna w praktyce: patrz stackoverflow.com/questions/253055#432518
VonC,
0

Jeśli używasz rozszerzeń Git: przejdź do ekranu Zatwierdź, na dole powinno znajdować się pole wyboru z napisem „Zmień zatwierdzenie”, jak widać poniżej:

wprowadź opis obrazu tutaj

batsheva
źródło
@KrunalPandya tak, lub po prostu naciśnij commit i push
batsheva