2009-07-10 15 views
123

W moim repozytorium git śledzącym repozytorium svn Dokonałem wielu zmian w jednym pliku.git selective revert zmiany lokalne z pliku

Teraz chcę przywrócić te zmiany (jak przywracanie svn), ale tylko części pliku.

Chcę móc wyświetlać różnice w pliku, odrzucać (przywracać) zmiany, których nie chcę i zachować pożądane zmiany.

komenda

git add -i 

wydaje się mieć możliwość, aby to zrobić, ale nie chcę, aby ten etap jeszcze.

Odpowiedz

74

Możesz to zrobić bezpośrednio za pomocą git checkout -p. Zobacz poniżej: Daniel Stutzbach's answer.


Old odpowiedź (przed checkout -p został wprowadzony):

Można to zrobić tak:

git add -i 

(wybierz kromkami chcesz zachować)

git commit -m "tmp" 

Teraz masz zatwierdzenie z tylko zmianami, które wykonałeś Do utrzymania, a reszta nie jest zapisana.

git reset --hard HEAD 

W tym momencie, niezatwierdzone zmiany zostały odrzucone, więc trzeba mieć czyste katalog roboczy, ze zmianami, które chcesz zachować popełnione na górze.

git reset --mixed HEAD^ 

ta usuwa ostatni commit ('tmp'), ale zachowuje zmiany w katalogu roboczym, Unstaged.

EDYCJA: zastąpiono --soft z --mixed, aby oczyścić obszar pomostowy.

+0

to spowoduje zmiany, które chcę zachować, prawda? Nie chcę jeszcze wprowadzać tych zmian. mm może podejmuję zobowiązania zbyt poważnie. Może powinienem teraz odpocząć, ponieważ wszystko odbywa się w lokalnym repozytorium. btw jaki jest reset git --soft HEAD^do? – Pradeep

+0

"git reset --soft HEAD ^" cofa commit w tym sensie, że zachowuje katalog roboczy i indeks taki jak był, i przenosi bieżące oddzwonienie do oddziału. –

+0

Dzięki Jakub. Paolo, dlaczego miałby miękki reset do głowy - 1 trzeba tutaj? Częściowe zatwierdzenie i twardy reset powinny być wystarczające, czy nie jest to utrzymanie pewnych zmian i odrzucenie innych? – Pradeep

3

Można uruchomić git diff na plik, zapisać wynikowy diff, edytować je, aby usunąć zmiany robisz chcesz zapisać, a następnie uruchom go poprzez patch -R cofnąć pozostałe dyferencjału.

git diff file.txt >patch.tmp 
# edit patch.tmp to remove the hunks you want to keep 
patch -R <patch.tmp
+0

Miałem 2 porcje w moim pliku poprawki i usunąłem jeden. Nie wiem, jaki jest powód, ale łatka -R wciąż jest odrzucana. – Pradeep

+2

W innym komentarzu wspominasz, że 'git diff' pokazuje cały plik jako zmieniony. Zwykle dzieje się tak, gdy zapisałeś plik, używając różnych zakończeń linii od tego, co poprzednio. To również spowoduje, że 'patch' odrzuci plik poprawki. Czy to brzmi jak to, co mogło się stać? –

+0

masz rację. zakończenia linii są przełączane za każdym razem, gdy używam polecenia patch. Jestem na oknach i używam kremu/vim. Najpierw muszę to uporządkować. – Pradeep

2

Wygląda chcesz

git revert --no-commit $REVSISON 

Następnie można użyć

git diff --cached 

zobaczyć co zmiana zostanie dokonana przed popełnienia (jako Operacja przywrócenia tylko zobowiązać się w kierunku do przodu, że replikuje odwrotność zmiany w przeszłości)

Jeśli byłeś z pur e repozytorium Git, możesz ewentualnie, w zależności od celów, użyć interaktywnego rebase (git rebase -i), aby powrócić do zatwierdzenia, które Ci się nie podobało i edytować commit z mocą wsteczną, aby zmiany, których nie lubisz, nigdy się nie wydarzyły, ale to ogólnie tylko dlatego, że WIEDZIEĆ już nigdy nie będziesz chciał go zobaczyć.

+0

Powróciłem, jak wspomniałeś poprzednią wersję (czy to prawda?), A teraz git diff pokazuje cały plik jako zmieniony. Ma pokazać edycje, które zrobiłem? – Pradeep

+0

to ma pokazać zmiany "wycofane" –

1

Ponownie czytając pytanie, brzmi to tak, jakbyś chciał przywrócić zmiany, które są w twoim drzewie roboczym, a nie zmiany, które zostały wcześniej zatwierdzone, ale niektóre z pozostałych odpowiedzi sprawiają, że brzmi to tak, jak moje czytanie może być błędne. Możesz wyjaśnić?

Jeżeli zmiany są możliwe tylko w kopii roboczej, najprostszym sposobem na to jest do etapu zmian, które chcesz zachować z:

git add -i <file> 

Potem wyrzucić zmiany, które nie chcą zachować, sprawdzając wersję indeksu:

git checkout -- <file> 

Then unstage zmian, jeśli nie chcesz je wystawił jeszcze:

git reset -- <file> 

Ten przepis tylko przywraca wybrane zmiany do pliku (lub plików określonych) i nie tworzy żadnego tymczasowego zatwierdzenia, które następnie wymaga przywrócenia.

Jeśli chcesz wybiórczo stosują tylko niektóre ze zmian dokonanych w poprzednich zatwierdzeń następnie można przywrócić plik do poprzedniego pierwszego stanu popełnione:

git reset <commit_before_first_unwanted_change> -- <file> 

Następnie można śledzić poprzednią recepturę git add -i <file> na scenie te zmiany, które chcesz zachować, git checkout -- <file>, aby wyrzucić niepożądane zmiany i git reset -- <file>, aby "anulować" zmiany.

279

Wierzę, że można to zrobić najprościej z:

git checkout -p <optional filename(s)> 

Z podręcznika:

−p, −−patch 
     Interactively select hunks in the difference between the <tree−ish> 
     (or the index, if unspecified) and the working tree. The chosen 
     hunks are then applied in reverse to the working tree (and if a 
     <tree−ish> was specified, the index). 
 This means that you can use git checkout −p to selectively discard 
     edits from your current working tree. 
+35

To naprawdę powinna być akceptowana odpowiedź, robi dokładnie to, co chcesz. – vdboor

+1

Ponadto, jeśli nie chcesz tego robić wybiórczo, możesz użyć "git checkout - ...", aby odrzucić zmiany. – db42

+0

Tak, rzeczywiście, dlaczego nie zmieniła się odpowiedź? – lkraav

0

opcje wiersza polecenia opisane w odpowiedziach Oto przydatny, gdy plik jest na serwerze, do którego uzyskuję dostęp przez terminal ssh. Jednak, gdy plik znajduje się na moim komputerze lokalnym, wolę następujący sposób:

Otwórz plik w edytorze netbeans (który jest obsługiwany przez git). Netbeans umieszcza czerwone/zielone/niebieskie znaki na numerach linii, aby wskazać, gdzie zostały usunięte/dodane/zmodyfikowane (odpowiednio).

Kliknięcie dowolnego z tych znaków daje możliwość cofnięcia tej zmiany. Ponadto można kliknąć prawym przyciskiem myszy na czerwone i niebieskie znaczniki, aby znaleźć starą wersję w wyskakującym okienku.