Cofnij zmianę w git (nie przepisywanie historii)
Dokonałem zmiany w scenariuszu i go popełniłem. Potem wprowadziłem kilka innych zmian i wrzuciłem je do zdalnego repozytorium i tym podobne.
Wtedy zdałem sobie sprawę, że pierwsza zmiana, o której wspomniałem, była głupia i chcę ją cofnąć.. Czy mogę "odpisać" ten commit bez ręcznego kopiowania / wklejania różnic?Jako przykład: mam dwa pliki, a.py
i b.py
:
Commit 1:
I delete a function in a.py
Commit 2:
I change a few lines in b.py
Commit 3:
I change the docstring in a.py
Czy mogę cofnąć usunięcie tej funkcji i sprawić, że będzie ona wyświetlana jako "commit 4" (zamiast usuwać commit 1)
4 answers
Tak, możesz do tego użyć git revert. Więcej informacji można znaleźć w sekcji podręcznika Gita na tej stronie.
Istotą jest to, że możesz powiedzieć:git revert 4f4k2a
Gdzie 4f4k2a jest identyfikatorem commita, który chcesz cofnąć, i będzie próbował go cofnąć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-28 13:45:07
Tylko komentarz:
git revert aCommit
Zwraca wszystkie commit (jak w "wszystkie pliki część commita"):
oblicza odwrotną łatkę, nakłada ją na HEAD I commit.
Więc dwa problemy tutaj (pierwszy jest łatwo rozwiązany):
- to zawsze commit, więc możesz chcieć dodać
-no-commit
option: "git revert --no-commit aCommit
": jest to przydatne przy przywracaniu więcej niż jednego efektu commitów do indeksu w wierszu. - Nie dotyczy konkretnego pliku (co jeśli a.py była częścią commita z 1000 innymi zmianami, których nie chcesz cofnąć) ?
W tym celu, jeśli chcesz wyodrębnić określone pliki w innym zatwierdzeniu, powinieneś zobaczyćgit-checkout
, w szczególnościgit checkout <commit> <filename>
składnia (nie jest to dokładnie to, czego potrzebujesz w tym przypadku)
Easy Git (Elijah Newren) próbował wprowadzić bardziej "kompletny revert" na listę dyskusyjną Git ; ale bez większego sukces:
LUDZIE od czasu do czasu chcą "cofnąć zmiany".
Teraz to może być:
- zmiany między 32 i 29 rewizji temu,
- mogą to być wszystkie zmiany od ostatniego commita,
- mogą to być zmiany od 3 commitów temu, lub
- to może być tylko jeden konkretny commit.
- użytkownik może chcieć podzestawić takie rewersy tylko do określonych plików ,
(eg revert
na udokumentowane tutaj , ale nie jestem pewien, czy jest to część obecnego rozkładu np.)
Ale wszystko sprowadza się do" powrotu zmian " w końcu.
eg revert --since HEAD~3 # Undo all changes since HEAD~3
eg revert --in HEAD~8 # much like git revert HEAD~8, but nocommit by default
eg revert --since HEAD foo.py # Undo changes to foo.py since last commit
eg revert foo.py # Same as above
eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch]
Czy te rodzaje "przywracania danych" naprawdę są tak różne, że powinny istnieć różne polecenia, czy też niektóre z tych operacji nie powinny być obsługiwane przez proste polecenie revert?
Oczywiście, większość użytkowników przez większość czasu prawdopodobnie będzie używać "eg revert FILE1 FILE2...
" forma, ale ja nie widziałem szkody w wspieraniu dodatkowych możliwości.Also...is czy jest coś fundamentalnego, co powstrzymałoby core git od przyjęcia takiego zachowania?
Eliasz
Notatka: commity domyślnie nie mają sensu dla uogólnionego polecenia
revert
, a "git revert REVISION
" powodowałoby błąd z instrukcjami (nakazującymi użytkownikowi dodanie flagi --in).
Powiedzmy, że masz, z 50 popełnionych, 20 plików zdajesz sobie sprawę, że stary commit x wprowadził zmiany, które nie powinny mieć miejsca.
Mała kanalizacja jest w porządku.
To, czego potrzebujesz, to sposób, aby wyświetlić listę wszystkich konkretnych plików, których potrzebujesz, aby przywrócić
(jak w "anulowanie zmian wprowadzonych w commicie X przy zachowaniu wszystkich kolejnych zmian"),
a potem dla każdego z nich:
git-merge-file -p a.py X X^
Problem polega na odzyskaniu utraconej funkcji bez niszczenia wszystkich późniejszych zmian w a.py lepiej zatrzymaj.
Technika ta nazywana jest czasem " negatywnym scalanie".
Od git merge-file <current-file> <base-file> <other-file>
środki:
zawiera wszystkie zmiany, które prowadzą od <base-file>
do <other-file>
w <current-file>
, możesz przywrócić usuniętą funkcję, mówiąc, że chcesz włączyć wszystkie zmiany.)
- from: X (gdzie funkcja została usunięta)
- do: X^ (poprzedni commit przed X, gdzie funkcja nadal tam była)
Uwaga:'-p
' argument, który pozwala na przegląd najpierw zmiany bez robienia czegokolwiek na bieżącym pliku. Gdy masz pewność, usuń tę opcję.
Uwaga :git merge-file
czy nie jest takie proste : nie można tak po prostu odwoływać się do poprzednich wersji pliku.
(miałbyś w kółko frustrujące przesłanie: error: Could not stat X
)
Musisz:
git cat-file blob a.py > tmp/ori # current file before any modification
git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted
git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there
git merge-file a.py tmp/X tmp/F # basically a RCS-style merge
# note the inversed commit order: X as based, then F
# that is why is is a "negative merge"
diff -u a.py tmp/ori # eyeball the merge result
git add a.py
git commit -m "function restored" # and any other changes made from X are preserved!
Jeśli ma to być zrobione dla dużej liczby plików w poprzednim commicie... niektóre skrypty są w porządku;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-15 01:43:01
Aby przywrócić zmiany tylko do jednego pliku w commicie, jak zauważył VonC, chciałbym checkout
gałąź (master lub trunk lub cokolwiek), a następnie checkout
wersję pliku, którą chciałem przywrócić i traktować jako nowy commit:
$ git checkout trunk
$ git checkout 4f4k2a^ a.py
$ git add a.py
$ git diff #verify I'm only changing what I want; edit as needed
$ git commit -m 'recover function deleted from a.py in 4f4k2a'
Prawdopodobnie jest komenda hydrauliczna, która zrobiłaby to bezpośrednio, ale nie użyłabym jej, gdybym wiedziała. Nie chodzi o to, że nie ufam Gitowi, ale nie ufam sobie . nie ufałbym, że wiem, nie patrząc na to, co zostało zmienione w tym pliku w tego zobowiązania i od tego czasu. Jak już spojrzę, łatwiej jest stworzyć nowy commit edytując diff
. Może to tylko osobisty styl pracy.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:48
Spójrz na to pytanie git revert . Wydaje się, że występuje problem z przywróceniem starszych commitów, jeśli nie w kolejnych sekwencjach, w tym najnowszych commitów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:59