Jak zdobyć tylko jeden plik z innej gałęzi


1261

Używam git i pracuję na gałęzi master. Ta gałąź ma plik o nazwie app.js.

Mam experimentoddział, w którym wprowadziłem wiele zmian i mnóstwo zmian. Teraz chcę przenieść wszystkie zmiany wykonane tylko do app.jsod experimentdo mastergałęzi.

Jak mogę to zrobić?

Po raz kolejny nie chcę łączenia. Chcę tylko przenieść wszystkie zmiany app.jsz experimentgałęzi na mastergałąź.



1
Poza odpowiedzią i innymi odpowiedziami na dzień dzisiejszy, jak skopiować zawartość pliku, tego właśnie chciałem, gdy ją znalazłem. Jednakże, jeśli dokładnie przeczytany, Nick chciał wprowadzić zmiany, a nie pełny tekst, a plik mastermoże się różnić experiment, np. Może zawierać zmiany scalone z innych gałęzi, które zostałyby utracone w pliku, jest po prostu kopiowany. PS z drugiej strony nie chce się łączyć, ale o ile wiem, git mergetermin dotyczy tylko gałęzi, a nie konkretnego pliku, więc tutaj nie ma sprzeczności.
Aleksiej Martianow

Odpowiedzi:


1599
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

Zobacz także git, jak cofnąć zmiany jednego pliku?


Aktualizacja sierpnia 2019, Git 2.23

W przypadku nowych poleceń git switchi git restorepoleceń będzie to:

git switch master
git restore -s experiment -- app.js

Domyślnie przywracane jest tylko działające drzewo.
Jeśli chcesz również zaktualizować indeks (czyli przywrócić zawartość pliku i dodać go do indeksu za pomocą jednego polecenia):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

Jak wspomina Jakub Narębski w komentarzach:

git show experiment:path/to/app.js > path/to/app.js

działa również, z tym wyjątkiem, że jak szczegółowo opisano w pytaniu SO „ Jak pobrać pojedynczy plik z konkretnej wersji w Git? ”, musisz użyć pełnej ścieżki z katalogu głównego repozytorium.
Stąd ścieżka / do / app.js użyta przez Jakuba w jego przykładzie.

Jak Frosty wspomina w komentarzu:

otrzymasz tylko najnowszy stan app.js

Ale dla git checkoutlub git showmożesz faktycznie odwoływać się do dowolnej wersji, jak zilustrowano w pytaniu SO „ git checkout wersja pliku w git gui ”:

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

byłoby tak samo, jak $ FILENAME to pełna ścieżka pliku wersjonowanego.

$REVISIONmoże być jak pokazano na git rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

i tak dalej.

schmijos dodaje w komentarzach :

możesz to również zrobić ze skrytki:

git checkout stash -- app.js

Jest to bardzo przydatne, jeśli pracujesz nad dwoma oddziałami i nie chcesz zatwierdzać.


13
Jedna uwaga: otrzymasz tylko najnowszy stan app.js, nie przeniesiesz żadnej historii z gałęzi eksperymentu.
Frosty

2
@ThomasReggi powinieneś być w stanie zaimportować (pobrać) plik z dowolnego oddziału do dowolnego bieżącego oddziału. Jeśli nie możesz, możesz zadać tutaj dobre pytanie, podając szczegółowe informacje, takie jak dokładny komunikat o błędzie oraz zastosowana wersja Git i systemu operacyjnego.
VonC

2
W podkatalogu możesz także użyć experiment:./app.js. (Nie musisz podawać pełnej ścieżki.) Nauczyłem się tego dzięki bardzo pomocnemu komunikatowi o błędzie git dał mi: „Czy chodziło Ci o„ mybranch: full / path / to / my / file.xsl ”aka” mybranch: ./file.xsl '? ” Tak! Nie sądzę, aby kiedykolwiek był tak zachwycony fatalnym komunikatem o błędzie.
Evan Lenz

1
@TomaszGandor Tak, wspominam o tym w stackoverflow.com/a/21066489/6309 , gdzie git show nie modyfikowałby indeksu, ale git Checkout modyfikuje indeks.
VonC

1
@FriedBrice Zobacz moją odpowiedź: w dzisiejszych czasach byłobygit restore -s new-feature path/to/app.js
VonC

358

Wszystko jest znacznie prostsze, użyj do tego git checkout.

Załóżmy you're on mastergałąź, aby uzyskać app.js from new-featuregałąź wykonaj:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

Spowoduje to wyświetlenie zawartości żądanego pliku. Możesz, jak zawsze, użyć części sha1 zamiast nazwy gałęzi nowej funkcji, aby pobrać plik tak, jak był w tym konkretnym zatwierdzeniu.

Uwaga : new-featuremusi to być oddział lokalny , a nie zdalny.


76
Pomocne jest zawsze określenie źródła, git checkout origin/source_branch path/to/fileponieważ jeśli zaniedbałeś aktualizację gałęzi źródłowej lokalnego repozytorium, możesz otrzymać starą wersję pliku ... Zapytaj mnie, skąd to wiem. ;)
taliryczny

2
@Mymozaaa w pytaniu nie wspomniano o pilotach, stąd założenie, że jest to czysto lokalne repozytorium
Dmitrij Avtonomow

1
Czy to polecenie przyniesie historię pliku, czy tylko ostatnią wersję pliku?
user1366265

1
@ user1366265 to polecenie umieści plik tak, jak był w określonym zatwierdzeniu lub na początku wskazanej gałęzi. Nie ma czegoś takiego jak „historia pliku”, wszystkie informacje historyczne są przechowywane tylko w gałęziach.
Dmitrij Avtonomov,

3
Wygląda na to, że automatycznie wyodrębnia pobrany plik. Czy można zrobić to samo bez inscenizacji?
bluenote10

44
git checkout branch_name file_name

Przykład:

git checkout master App.java

To nie zadziała, jeśli nazwa twojego oddziału zawiera kropkę.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.

@PhilipRego Ta odpowiedź jest poprawna. Domyślam się, że w twoim oddziale jest inna litera lub interpunkcja, albo masz tylko oddział zdalny, a nie lokalny. Zobacz dokument git Checkout: git-scm.com/docs/git-checkout#Documentation/...
Bret,

@Bret Znalazłem, że to nie działa, gdy nazwa oddziału ma kropkę. Zasugerowałem edycję
Philip Rego,

To najlepsza odpowiedź. Chciałbym, żeby ta odpowiedź była najwyżej oceniana. Obecny najwyższy jest bardzo zagmatwany i nie jest prosty
Russell Lego

41

Uzupełnienie odpowiedzi VonC i chhh.

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

lub

git checkout experiment -- app.js

2
Fajne! Nienawidzę określać długich ścieżek. Czy podwójne myślniki ( --) między nazwą gałęzi a ścieżkami są opcjonalne? Czy to tylko po to, aby ścieżki, które zaczynałyby się od myślnika, nie były traktowane jako opcje / przełączniki?
Tomasz Gandor,

Szczerze mówiąc nie wiem. Nawet nie zauważyłem, że zapomniałem o podwójnej desce rozdzielczej, dopóki nie zwróciłeś na to uwagi.
AlexLordThorsen

6
@TomaszGandor --Jest opcjonalny, ale bardziej przydatny, aby uniknąć konfliktu z nazwami oddziałów. Na przykład git checkout -- foooznacza „pobierz plik foo z HEAD” (tzn. Zastąp lokalne zmiany w foo , tj. Podzbiór git reset --hard), ale git checkout foomoże to oznaczać, że lub „przejdźmy do gałęzi foo ”.
Alois Mahdal

8

Lub jeśli chcesz wszystkie pliki z innej gałęzi:

git checkout <branch name> -- .

23
Początkowy queston zawiera „tylko jeden plik”.
greatvovan

1
zastępuje to istniejące pliki zamiast scalania
Amare

3
To .ogromna różnica: zamiast przenosić się do innej gałęzi, kopiuje wszystkie pliki stamtąd, pozostawiając cię na bieżącym. Dostajesz treść z innej branży bez wchodzenia w nią.
Xeverous,

4

Przejrzyj plik na github i stamtąd

Jest to pragmatyczne podejście, które nie odpowiada bezpośrednio PO, ale niektóre okazały się przydatne:

Jeśli gałąź znajduje się w GitHub, możesz przejść do żądanej gałęzi i pliku za pomocą dowolnego z wielu narzędzi oferowanych przez GitHub, a następnie kliknij „Raw”, aby wyświetlić zwykły tekst, i (opcjonalnie) skopiuj i wklej tekst jako pożądany.

Podoba mi się to podejście, ponieważ pozwala spojrzeć na cały plik zdalny przed wyciągnięciem go na komputer lokalny.


2
Jednak kopiowanie i wklejanie nieprzetworzonego pliku może powodować niepożądane zmiany znaków w twoim git diff. Bezpieczniej jest zapisać plik bezpośrednio w projekcie, aby nie wprowadzać żadnych zmian.
Philip Rego

0

Jeśli chcesz plik z konkretnego zatwierdzenia (dowolnej gałęzi), powiedz 06f8251f

git checkout 06f8251f ścieżka_do_pliku

na przykład w systemie Windows:

git checkout 06f8251f C: \ A \ B \ C \ D \ file.h


1
Dziękujemy za poświęcenie czasu na odpowiedź! Ale to nie odpowiada na pytanie, a dobra odpowiedź, która jest bardzo zdeterminowana, została już opublikowana 9 lat temu. Nie ma potrzeby podważać pytania.
Nathan

To ważny praktyczny scenariusz. Odpowiedź dotyczy poprawnie gałęzi, ale co z przeglądaniem konkretnego zatwierdzenia gałęzi.
arupjbasu

0

Innym sposobem jest utworzenie łatki z różnicami i zastosowanie jej na przykład w gałęzi master. Powiedzmy, że ostatnie zatwierdzenie przed rozpoczęciem pracy nad app.js to 00000aaaaa, a zatwierdzenie zawierające żądaną wersję to 00000bbbbb

Uruchomisz to w gałęzi eksperymentu:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

Spowoduje to utworzenie pliku ze wszystkimi różnicami między tymi dwoma zatwierdzeniami dla pliku app.js, które można zastosować w dowolnym miejscu. Możesz zachować ten plik w dowolnym miejscu poza projektem

Następnie w trybie głównym po prostu uruchom:

git apply ~/app_changes.git

teraz zobaczysz zmiany w projektach, jakbyś dokonał ich ręcznie.


-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Mam nadzieję, że to ci pomoże. Daj mi znać, jeśli masz jakieś pytania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.