Selektywnie przywrócić lub wypisać zmiany w pliku w Git?

88

Czy istnieje polecenie, które pozwala częściowo cofnąć zmiany w pliku (lub plikach) w katalogu roboczym?

Załóżmy, że dużo edytujesz plik, ale zdajesz sobie sprawę, że chcesz cofnąć niektóre zmiany z powrotem do stanu zatwierdzonego, ale nie inne zmiany.

Wyobrażam sobie opcję, git checkoutktóra działa podobnie git add -p, tj. Przechodzi przez plik kawałek po kawałku i pyta, czy chcesz go zachować, czy nie.

1800 INFORMACJE
źródło

Odpowiedzi:

85

Możesz użyć

git add -p <path>

aby przygotować fragmenty, które chcesz zachować w określonym pliku, a następnie

git checkout -- <path>

aby odrzucić zmiany w drzewie roboczym, których nie chciałeś zachować, sprawdzając przemieszczoną wersję pliku.

Wreszcie możesz użyć

git reset -- <path>

aby przywrócić ustawioną wersję pliku do najnowszej zatwierdzonej wersji pliku, aby pozostawić zmiany bez zmiany.

CB Bailey
źródło
W tym prostym przypadku użycia, który każdy inny system kontroli wersji nazywa po prostu „revert”, dlaczego polecenie Git jest tak niejasne?
Jan Hettich
5
@Jan Czy polecenie innych systemów kontroli wersji revertpozwala wybrać, które zmiany w pliku mają zostać cofnięte ? Szczerze pytam, ponieważ mam doświadczenie tylko z CVS i Git. W Git git checkout -- path/to/fileto pojedyncze polecenie, które przywraca wszystkie zmiany w tym pliku, ale nie jest to to samo, co powyżej.
michiakig
3
Jest też git checkout --patchi git reset --patchktóre działa jak git add --patchw najnowszym gicie.
Matt Connolly
2
@Rudie, --zwykle wskazują koniec parsowania opcji i że wszelkie argumenty, które pojawiają się po nim, mają być interpretowane dosłownie. Oznacza to, że nie musiałbyś dodawać ./przed jakąkolwiek nazwą pliku zaczynającą się od znaku minus, jeśli nazwa pliku następuje po --.
zrajm
kiedy używam git checkout --patchróżnicy, wydaje się, że jest wstecz. Symbole minus DODAWANIE tekstu do mojej kopii roboczej, a symbole plusa USUWANIE wierszy z kopii roboczej.
Felipe Alvarez
115

Z wersją gita> = 1.7.1 mogę

git checkout -p

Nie jestem pewien, kiedy ta funkcja została wprowadzona.

thisgeek
źródło
11
Warto wspomnieć, że można również git reset -pselektywnie odstawić zmiany od obszaru / indeksu. Nie wiem też z góry, w której wersji Gita to zostało wprowadzone.
To jest poprawna odpowiedź, dlaczego nie została zaakceptowana.
wukong
1
@wukong, ponieważ ta odpowiedź została opublikowana 2 lata po zadaniu pytania. W tej chwili (2009) odpowiedź Charlesa była najlepszym rozwiązaniem
pomeh
8

git checkout $fileprzywraca stan pliku $filedo ostatniego zatwierdzonego stanu. Myślę, że możesz użyć git checkout SHA-1 -- $filedo przywrócenia pliku do zatwierdzenia zidentyfikowanego przez SHA-1.

Koraktor
źródło
1
tak, nie do końca to, czego chcę, ponieważ chcę zachować niektóre zmiany, które wprowadziłem w pliku, a cofnąć inne
1800 INFORMACJE
1

Z ilu zatwierdzeń musisz wrócić i wybrać spośród nich? Jeśli to tylko jeden, może weź gałąź tuż przed nim, wyewidencjonuj zatwierdzony plik, a następnie użyj go, git add -paby dodać go tak, jak chciałeś. Następnie możesz wrócić do miejsca, w którym byłeś i pobrać plik z gałęzi tymczasowej.

to jest:

git checkout -b temp troublesome-commit^
git checkout troublesome-commit -- path/to/file
git add -p path/to/file
git commit -c troublesome-commit
git checkout @{-1}
git checkout temp -- path/to/file
git commit path/to/file
git branch -D temp

Inne alternatywy obejmują cofnięcie się i edycję zatwierdzenia za pomocą git rebase -i(oznaczenie zatwierdzenia jako edit, a następnie wykonanie a git reset HEAD^i ponowne wykonanie zatwierdzenia po wrzuceniu z powrotem do powłoki).

Jeśli zmiany, z których musisz dokonać wyboru, są rozłożone na serię zatwierdzeń, może być lepiej wyodrębnić je jako łaty (lub łatkę obejmującą wszystkie z nich) i ręcznie edytować łatkę, usuwając zmiany, które chcesz zachować, i wprowadzanie pozostałości do git apply --reverse.

araqnid
źródło
Tak naprawdę nie chcę cofać niczego, co zostało popełnione, chcę cofnąć zmiany, które są tylko w mojej kopii roboczej
1800 INFORMACJE