Git: Jak zaktualizować / pobrać pojedynczy plik ze wzorca źródła zdalnego?

362

Scenariusz:

  1. Wprowadzam pewne zmiany w jednym pliku lokalnie i uruchamiam git add, git commitigit push
  2. Plik jest przekazywany do głównego repozytorium zdalnego źródła
  3. Mam inne lokalne repozytorium, które jest wdrażane za pośrednictwem Capistrano metodą „remote_cache” z tego zdalnego repozytorium
  4. Teraz nie chcę wdrażać całej aplikacji, ale po prostu zaktualizować / pobrać ten pojedynczy plik.

Czy jest to jakoś możliwe w przypadku git? Nie byłem w stanie znaleźć niczego, co by działało, ani nie byłem w stanie tego rozgryźć. Z SVN właśnie to zrobiłem svn up filei voila.

foresth
źródło
19
Możesz rozważyć zmianę zaakceptowanej odpowiedzi na tę, która faktycznie odpowiada na twoje pytanie. ;)
kroki
6
Po ponad 6 latach uważam, że możemy bezpiecznie założyć, że tak się nie stanie @steps ...
Félix Gagnon-Grenier
Z Git 2.23 (sierpień 2019) tak jest git restore -s origin/master -- path/to/file. Zobacz moją odpowiedź poniżej .
VonC

Odpowiedzi:

914

Można to zrobić (we wdrożonym repozytorium)

git fetch
git checkout origin/master -- path/to/file

Pobieranie pobierze wszystkie ostatnie zmiany, ale nie umieści go w bieżącym wypisanym kodzie (obszarze roboczym).

Kasa zaktualizuje drzewo robocze o konkretny plik z pobranych zmian ( origin/master).

Przynajmniej działa to dla mnie w przypadku tych małych drobnych poprawek literowych, w których dziwne jest tworzenie gałęzi itp. Tylko po to, aby zmienić jedno słowo w pliku.

qzio
źródło
1
Bardzo przydatny, działało świetnie. Musiałem pobrać plik composer.json i uruchomić aktualizację, zanim zaktualizowałem resztę strony w produkcji. Gdybym ręcznie umieścił pliki composer.json / lock na swoim miejscu, kiedy wykonałem ściąganie, byłoby sprzeczne z informacją, że pliki już istniały. W ten sposób git rozpoznał pliki bez reklamacji.
David
6
Oto odpowiedź, której szukałem.
javadba
20
@Mymozaaa Podwójny myślnik oznacza, że ​​po nim następuje nazwa pliku. Ma to uniemożliwić gitowi interpretowanie nazwy pliku jako gałęzi w niefortunnym przypadku, gdy masz dwa o tej samej nazwie.
Joel Mellon
Problem polega na tym, że nadal pobierasz, a jeśli to duże repozytorium, będzie to kosztowna operacja. Obawiam się, że jedyną alternatywą byłoby zainstalowanie gitweb na pilocie, a następnie uzyskanie dostępu do niego w celu odzyskania pliku.
Christian Goetze,
małe pytanie, po zrobieniu tego, idę na inną maszynę, następnie wykonuję twoje akcje wymienione powyżej, ale potem git statuswidzę je jako Changes to be committed:- co oznacza, że ​​muszę je ponownie popełnić? (tylko zauważając, że chciałem odświeżyć pojedynczy nietknięty plik, ale samo repozytorium jest dotykane na innym komputerze)
Ricky Levi
42

Dla mnie działał następujący kod:

     git fetch
     git checkout <branch from which file needs to be fetched> <filepath> 
Shagun Pruthi
źródło
19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip
Dmitry R.
źródło
1
To dobre rozwiązanie dla repon sklonowanych przez ssh, ale wygląda na to, że nie jest obsługiwane przez https: git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x Daje mi komunikat o błędzie:fatal: Operation not supported by protocol.
Alderath
1
było fajnie połączone z tar: s --to-stdout,git archive --remote="gitolite3@<host>:<repo>" <tag> <file> | tar xf - --to-stdout
Puggan Se
18

Z Git 2.23 (sierpień 2019 r.) I nową (wciąż eksperymentalną) komendą git restore, zobaczoną w „ Jak zresetować wszystkie pliki z katalogu roboczego, ale nie z obszaru przejściowego? ”, Byłoby to:

git fetch
git restore -s origin/master -- path/to/file

Chodzi o to, że: git restorezajmuje się tylko plikami, a nie plikami i gałęziami git checkout.
Zobacz „ Mylić przezgit checkout ”: to jest, gdzie git switchwchodzi)


codersam dodaje w komentarzach :

w moim przypadku chciałem pobrać dane z mojego upstream (z którego rozwidliłem).
Właśnie zmieniłem na:

git restore -s upstream/master -- path/to/file
VonC
źródło
2
Cóż za ulga, że ​​to polecenie w końcu istnieje ... Co robili wcześniej nieświadomi ludzie? Przywracałem całość i kopiowałem pojedyncze pliki, których potrzebowałem, ale było to bolesne.
Mike Wise,
To działało dla mnie, ale w moim przypadku chciałem uzyskać dane z mojego upstream (z którego rozwidliłem). Właśnie zmieniłem nagit restore -s upstream/master -- path/to/file
coderSam
@coderSam Dziękujemy za informację zwrotną. W odpowiedzi umieściłem twój komentarz dla większej widoczności.
VCC
8

Co możesz zrobić to:

  1. Zaktualizuj lokalne repozytorium git:

    git fetch

  2. Zbuduj lokalny oddział i dokonaj w nim kasy:

    git branch pouet && git checkout pouet

  3. Zastosuj zatwierdzenie, które chcesz w tej gałęzi:

    git cherry-pick abcdefabcdef

    (abcdefabcdef to sha1 zatwierdzenia, które chcesz zastosować)

ząbkować
źródło
4
Nawiasem mówiąc, twój drugi krok można również wykonać za pomocą jednego polecenia jako git checkout -b pouet.
Greg Hewgill
4
„pouet” to najlepsza nazwa oddziału dla tego przykładu.
Hussard,
2

Lub git stash (jeśli masz zmiany) w gałęzi, w której się znajdujesz, kasie głównej, wyciągnij najnowsze zmiany, pobierz ten plik na pulpit (lub całą aplikację). Przejdź do gałęzi, w której byłeś. Skrytka Git stosuje się z powrotem do stanu, w którym byłeś, a następnie napraw zmiany ręcznie lub przeciągnij, zastępując plik.

Ten sposób nie jest zbyt fajny, ale zdecydowanie działa, jeśli nie możecie wymyślić nic innego.

jahrichie
źródło
-10

Myślę, że znalazłem łatwy hack.

Usuń plik, który masz w lokalnym repozytorium (plik, który chcesz zaktualizować z ostatniego zatwierdzenia na serwerze zdalnym)

A potem zrób git pull

Ponieważ plik zostanie usunięty, nie będzie konfliktu

Viswadeep Sarangi
źródło
To usuwa wszystkie ewentualne zmiany wprowadzone lokalnie do tego pliku, a także ściąga wszystkie inne pliki, czego dokładnie nie chce OP.
legrojan
Zamiast aktualizować zdalną gałąź, usuwanie lokalne jest bardzo złym pomysłem.
c0der512,