Jak zmienić poprzednie zatwierdzenie, aby uwzględnić pominięty plik?

98

Popełniłem zmianę i zapomniałem dodać plik do zbioru zmian. Po innych zatwierdzeniach zdałem sobie sprawę, że brakuje pliku w HEAD^4zatwierdzeniu.

Jak przepisać poprzednie zatwierdzenie, aby uwzględnić brakujący plik?

kolrie
źródło
czy nacisnąłeś te 4 zatwierdzenia?
mvp
@mvp nie, są one tylko w moim lokalnym repozytorium git.
kolrie

Odpowiedzi:

54

Użyj git rebase --interactive HEAD~4i ustaw editopcję dla zatwierdzenia, które chcesz zmienić.

Pamiętaj, że nie powinieneś w ten sposób modyfikować zatwierdzeń wysyłanych do zdalnego repozytorium. W takim przypadku lepiej jest dodać nowe zatwierdzenie z brakującym plikiem.

Rafał Rawicki
źródło
Dzięki. Czy tak jest, nawet jeśli jestem jedynym użytkownikiem zdalnego repozytorium? Czy nie pozwoliłoby mi to zrobić, git push -fgdybym był pewien, że upstream się nie zmienił?
kolrie
1
Jeśli jesteś jedynym użytkownikiem zdalnego repozytorium, możesz wykonać wymuszone wypychanie.
Rafał Rawicki
7
Myślę, że te instrukcje nie są wystarczająco szczegółowe. Próbując go po raz pierwszy usłyszałem komunikat „Nie można zmienić bazy danych: Twój indeks zawiera niezatwierdzone zmiany”. Ja już add-ED brakujące pliki, więc zrobiłem commit z „xxx” jako wiadomości. Następnie wykonałem polecenie rebase i zmieniłem zatwierdzenie „xxx” z „wybierz” na „edytuj”. Następnie wykonałem polecenie „git rebase --continue”. Teraz, kiedy patrzę na historię, mam „xxx” jako ostatnie zatwierdzenie, a wcześniejsze zatwierdzenie, do którego chciałem je dodać, pozostaje niezmienione! Zastanawiam się, gdzie był mój błąd?
Darren Cook
2
Zgniatanie ostatniego zatwierdzenia nie spowoduje umieszczenia pliku w HEAD ~ 4.
Justin
1
git add editedFiles; git commit -m "Bla"; git rebase -i HEAD ~ 5; // tak jak teraz dodano nowe zatwierdzenie, więc musieliśmy zmienić bazę z 5 zamiast 4. teraz przenieś zatwierdzenie "Blah" do drugiej linii i zmień je z "Pick" na "s" (squash), co zmiażdży zatwierdzenie za pomocą HEAD ~ 5, ponieważ polecenia są wykonywane od góry do dołu
zstring
274

Zdaję sobie sprawę, że ludzie mogą wyszukiwać w wyszukiwarce Google i przychodzić tutaj, aby znaleźć prostszą odpowiedź: a co, jeśli to tylko ostatnie zatwierdzenie? (Pytanie OP dotyczy naprawienia czwartego zatwierdzenia w historii)

Jeśli zdecydujesz się zatwierdzić i zdasz sobie sprawę, że zapomniałeś od razu dodać plik , po prostu wykonaj:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

Gdzie --no-editzachowa ten sam komunikat o zatwierdzeniu.

Bułka z masłem!

Dr Beco
źródło
21
To jest odpowiedź.
Adam Bittlingmayer
5
Warto wspomnieć, jeśli zatwierdzenia nie są przesyłane do pilota.
Ram Patra
1
Tak, warto tu wspomnieć w komentarzach: Służy do użycia przed push . Dzięki za wskazanie tego.
Dr Beco
2
Jedna uwaga jest taka, że ​​zatwierdzenia przed i po --amendmają różne skróty
sonlexqt
6
Dzięki, ale to niemożliwe: poprosił OP HEAD^4. Tak jest w porządku, tylko jako dodatek w celach informacyjnych. ;)
Dr Beco
11

Jeśli NIE wypchnąłeś tych 4 zatwierdzeń, możesz to zrobić w następujący sposób:

Utwórz pliki łatek dla wszystkich tych zatwierdzeń:

git format-patch -4

Przewiń wstecz o 4 zatwierdzenia:

git reset --hard HEAD~4

Dodaj brakujący plik:

git add missing-file

Zatwierdź to za pomocą --amend:

git commit --amend

Zastosuj wszystkie zapisane poprawki z powrotem:

git am *.patch

Jeśli nacisnąłeś, NIE powinieneś używać tej metody. Zamiast tego po prostu przyznaj się do pomyłki i utwórz jeszcze jedno zatwierdzenie na szczycie HEAD, które rozwiązuje ten problem.

mvp
źródło
Jeśli chcesz zrobić to krok po kroku, łatwiej jest wybrać najlepsze zmiany po zmodyfikowanym, niż wyeksportować je jako łatkę.
Rafał Rawicki
1
To kwestia gustu. Lubię git format-patch/ git amznacznie lepiej. Co najważniejsze, daje ci to większą pewność, jeśli coś schrzanisz - zatwierdzenie zapisane jako łatka w fizycznym pliku jest najlepszą siecią bezpieczeństwa.
mvp,
Prawdziwe zaufanie polega na tym, że działając na repozytorium git nigdy niczego nie usuwasz. Stare commity są dostępne do startu git gc:)
Rafał Rawicki
To jest trywialne i oczywiste dla ciebie i dla mnie. Ale dla użytkownika, który dopiero zaczyna i prawdopodobnie nie rozumie nic o git - ten fakt wcale nie jest oczywisty.
mvp
2
Te instrukcje wydawały się rozwlekłe, ale były dość proste i łatwe do wykonania. Dzięki. (Chciałbym tylko dodać końcowy etap: rm *.patch)
Darren Cook
9

Chociaż zaakceptowana odpowiedź jest poprawna, brakuje w niej szczegółowych instrukcji, jak przeprowadzić edycję zatwierdzenia podczas procesu rebase.

  • Najpierw rozpocznij proces rebase:

    git rebase --interactive HEAD~4
    
  • Zostanie wyświetlona lista zatwierdzeń, wybierz zatwierdzenie, które chcesz edytować, zmieniając słowo pickna editi zapisz plik.

  • Wprowadź niezbędne modyfikacje w swoim kodzie (pamiętaj, aby wywołać git addnowe pliki)

  • Po wykonaniu wszystkich modyfikacji wydaj git commit --amend- to zmieni zatwierdzenie oznaczone jakoedit

  • Wywołanie git rebase --continue, które zakończy proces (jeśli jest więcej zatwierdzeń oznaczonych jako edit, powyższe kroki należy powtórzyć)

Ważne notatki:

  • NIE usuwaj linii oznaczonych jako pick, których nie chcesz edytować - pozostaw je bez zmian. Usunięcie tych wierszy spowoduje usunięcie powiązanych zatwierdzeń

  • GIT zmusza cię do zmiany stashbazy, jeśli twój katalog roboczy nie jest czysty; możesz jednak git stash pop / git stash applypodczas rebase, aby zmienić te zmiany (tj. zmiany schowane przed rozpoczęciem procesu rebase) do zatwierdzenia oznaczonego jakoedit

  • jeśli coś poszło nie tak i chcesz cofnąć zmiany dokonane podczas procesu rebase przed jego zakończeniem (tj. chcesz powrócić do punktu przed rozpoczęciem rebase), użyj git rebase --abort- przeczytaj również: Jak przerwać interaktywną rebase, jeśli --abort nie robi t działa?

  • Jak powiedziano w zaakceptowanej odpowiedzi:

    Pamiętaj, że nie powinieneś w ten sposób modyfikować zatwierdzeń przesyłanych do zdalnego repozytorium. W takim przypadku lepiej jest dodać nowe zatwierdzenie z brakującym plikiem.

    Odpowiedź dlaczego znajduje się w Git Book (akapit zatytułowany „ The Perils of Rebasing ”):

    Nie zmieniaj bazy zatwierdzeń, które istnieją poza repozytorium.

    Jeśli zastosujesz się do tej wskazówki, wszystko będzie dobrze. Jeśli tego nie zrobisz, ludzie będą cię nienawidzić, a przyjaciele i rodzina będą cię gardzić.

    Kiedy zmieniasz bazę, porzucasz istniejące zatwierdzenia i tworzysz nowe, które są podobne, ale różne. Jeśli gdzieś popchniesz zatwierdzenia, a inni ściągną je i oprze na nich pracę, a następnie przepiszesz te zatwierdzenia za pomocą git rebase i ponownie je popchniesz, Twoi współpracownicy będą musieli ponownie scalić swoją pracę, a gdy spróbujesz, wszystko się pogmatwa wciągnij ich pracę z powrotem do swojej.

    […]

dominik
źródło