Jak wybierać zmiany tylko dla jednego pliku, a nie całego zatwierdzenia

108

Muszę przenieść zmiany wprowadzone w jednym oddziale do innego. Mogę to zrobić za pomocą Cherry Pick. Jednak w moim przypadku chcę zastosować zmiany, które są istotne tylko dla jednego pliku, nie muszę wybierać całego zatwierdzenia. Jak to zrobić?

jak on
źródło

Odpowiedzi:

137

Masz różne opcje w zależności od tego, co chcesz osiągnąć:

Jeśli chcesz, aby zawartość pliku była taka sama jak w gałęzi docelowej, możesz użyć git checkout <branch> -- <filename>. Nie będzie to jednak „wybierać” zmian, które zaszły w pojedynczym zatwierdzeniu, ale po prostu przyjmie wynikowy stan wspomnianego pliku. Więc jeśli dodałeś linię w zatwierdzeniu, ale poprzednie zatwierdzenia zmieniły się bardziej i chcesz tylko dodać tę linię bez tych innych zmian, to pobranie nie jest tym, czego chcesz.

W przeciwnym razie, jeśli chcesz zastosować poprawkę wprowadzoną w zatwierdzeniu tylko do jednego pliku, masz wiele opcji. Możesz uruchomić git cherry-pick -n, tj. Bez zatwierdzania go, edytować zatwierdzenie (na przykład zresetować wszystkie pliki za pomocą git reset -- .i dodać tylko ten plik, który chcesz zmienić za pomocą git add <filename>). Lub możesz utworzyć różnicę dla pliku i zastosować ją następnie:

git diff <branch>^..<branch> -- <filename> | git apply
szturchać
źródło
22

Utwórz patch filei zastosuj.

git diff branchname -- filename > patchfile
git apply patchfile

EDYTOWAĆ:

Ponieważ musisz pobrać zmiany z zatwierdzenia, utwórz łatkę w następujący sposób:

git show sha1 -- filename > patchfile
Sailesh
źródło
1
git diff sha1(lub git diff branch- jest tak samo, jeśli gałąź wskazuje na ten sam skrót) wygeneruje tylko różnicę bieżącego katalogu roboczego w odniesieniu do tego skrótu, ale nie to, co zmienia zatwierdzenie wprowadzone samodzielnie.
szturchnij
Poprawny. Edytowałem odpowiedź. Dzięki.
Sailesh
1
-1 git checkoutz nazwą pliku to właściwy młotek do tego gwoździa. Obie te opcje są niepotrzebnie złożone.
Rein Henrichs
7
W tym konkretnym przypadku tak. Ale ogólnie, jeśli chcesz wybrać zmiany z zatwierdzenia dokonanego w określonym pliku, to checkoutnie zadziała, ponieważ może obejmować inne niechciane wcześniejsze zmiany i może nie zawierać zmian wprowadzonych w bieżącej gałęzi.
Sailesh
11

Inną przydatną rzeczą jest pobranie poprawki lokalnie, a następnie użycie:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

To jednak nie jest najlepszy wybór.

0x90
źródło
2
Ostrzeżenie: jak @poke mówi w swojej odpowiedzi, to nie kopiuje zmian; kopiuje cały stan pliku. Więc jeśli chcesz dodać zmiany zatwierdzone do pliku, to sprawdzając w ten sposób, w końcu nadpisujesz wszystkie nowsze zmiany, co nie jest dobre.
Alexander Bird
7

Git ma wszystko gotowe :)

Po prostu użyj git checkout <sha> <path-to-file>

Raghotham S
źródło
4
To nie jest najlepszy wybór - to sprawdzenie pliku w całości. Celem jest dokonanie określonej zmiany z zatwierdzenia. Często to to samo, ale czasami tak nie jest.
AndrewF
6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

działa to, jeśli chcesz skopiować pojedynczy plik z innej gałęzi do bieżącej gałęzi roboczej

Ismail Iqbal
źródło
1
Uważaj, zmiany wprowadzone w pliku, których nie ma w wersji z innej gałęzi, zostaną utracone.
Patrick Schlüter
Zgadzam się z tym. jest to przydatne, jeśli potrzebujesz tylko kopii pliku i chcesz go zmienić w bieżącej gałęzi
Ismail Iqbal
1
Można użyć globów (ścieżka / *) i podać więcej niż jedną ścieżkę / plik
Todd
1

Oto czego szukasz:

git checkout target-branch sha1 path/to/file

sha1 jest opcjonalne

Rusłan Osipow
źródło
11
nie, „wybierz zmiany w zatwierdzeniu” nie oznacza „wybierz cały plik”
Abyx,
1

Zwykle używam git ls-tree

po prostu zrób:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

Spowoduje to wydrukowanie wszystkich nazw plików pasujących do twojego grep i da klucze SHA1 plików w zatwierdzeniu.

Git show może być również używany do plików spoza twojej gałęzi. użycie >ze swojej powłoki potokiem wyjścia do pliku daje wynik, którego szukasz.

Alex
źródło
0

Możesz spróbować to zrobić:

git show COMMIT_ID -- path/to/specific-file | git apply

Na przykład:

git show 3feaf20 -- app/views/home/index.html | git apply
arashb31
źródło
-9
git reset HEAD~1

przenosi pliki do etapu przed zatwierdzeniem

git stash

usuwa z pamięci

Teraz twoja gałąź jest całkiem czysta (przywrócona do poprzedniego zatwierdzenia)

Venkata
źródło