Git: Как обновить / извлечь один файл из мастера удаленного источника?


363

Сценарий:

  1. Я делаю некоторые изменения в одном файле локально и запускаю git add, git commitиgit push
  2. Файл помещается в главный репозиторий удаленного источника.
  3. У меня есть другой локальный репозиторий, который развертывается через Capistrano с помощью метода «remote_cache» из этого удаленного репозитория
  4. Теперь я не хочу развертывать приложение целиком, а просто обновлять / извлекать этот единственный файл.

Возможно ли это как-то с помощью git? Я не смог найти ничего, что могло бы сработать, и не смог понять это. С SVN я просто так svn up fileи сделал .


20
Возможно, вы захотите изменить принятый ответ на тот, который действительно отвечает на ваш вопрос. ;)
шаги

7
По прошествии более 6 лет, я полагаю, мы можем с уверенностью предположить, что этого не произойдет @steps ...
Феликс Ганьон-Гренье

С Git 2.23 (август 2019) это так git restore -s origin/master -- path/to/file. Смотрите мой ответ ниже .
VonC

Ответы:


916

Это можно сделать (в развернутом репозитории)

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

Выборка загрузит все последние изменения, но не добавит их в ваш текущий извлеченный код (рабочая область).

Оформление обновит рабочее дерево с конкретным файлом из загруженных изменений ( origin/master).

По крайней мере, это работает для тех маленьких исправлений опечаток, когда кажется странным создавать ветку и т. Д., Просто чтобы изменить одно слово в файле.


1
Супер удобно, это работало отлично. Мне нужно было получить файл composer.json и запустить обновление, прежде чем я обновлю остальную часть сайта в рабочем состоянии. Если бы я вручную поместил файлы composer.json / lock на место, когда я выполнял извлечение, это могло бы привести к конфликту, говоря, что файлы уже существуют. Делая это таким образом, git распознал файлы без жалоб.
Дэвид

6
Это ответ, который я искал.
Джавадба

20
@Mymozaaa Двойная черта обозначает, что ниже следует имя файла. Это нужно для того, чтобы git не интерпретировал имя вашего файла как ветвь в неудачном случае, когда у вас есть два с одинаковым именем.
Джоэл Меллон

Проблема в том, что вы все еще получаете, и если это большой репо, это будет дорогая операция. Я боюсь, что единственной альтернативой будет установить gitweb на удаленном компьютере, а затем получить к нему доступ, чтобы получить файл или что-то подобное.
Кристиан Гетце

Небольшой вопрос, после этого я собираюсь на другую машину, затем я делаю ваши действия, перечисленные выше, но затем git statusя вижу их как ... то Changes to be committed:есть, мне нужно снова их зафиксировать? (только отмечая, что я хотел обновить один нетронутый файл, но сам репо затрагивается на другом компьютере)
Рики Леви,


19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip

1
Это хорошее решение для репозиториев, клонированных через ssh, но, кажется, это не поддерживается через https: git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x выдает мне сообщение об ошибке:fatal: Operation not supported by protocol.
Alderath

1
было приятно в сочетании с tar: S --to-stdout,git archive --remote="gitolite3@<host>:<repo>" <tag> <file> | tar xf - --to-stdout
Puggan Se

19

С Git 2.23 (август 2019 г.) и новой (все еще экспериментальной) командой git restore, показанной в разделе « Как сбросить все файлы из рабочего каталога, но не из промежуточной области? », Это будет:

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

Идея такова: git restoreимеет дело только с файлами, а не с файлами и ветками, как это git checkoutделается.
Смотрите « Смущенныйgit checkout »: вот, где git switchприходит)


Codersam добавляет в комментариях :

в моем случае я хотел получить данные из моего апстрима (из которого я разветвлялся).
Так что просто изменилось на:

git restore -s upstream/master -- path/to/file

2
Какое облегчение, что эта команда наконец-то существует ... Что раньше делали глупые люди? Я восстанавливал все это и копировал нужные мне файлы, но это было больно.
Майк Уайз

Это сработало для меня, но в моем случае я хотел получить данные из моего апстрима (из которого я разветвлялся). Так что просто поменял наgit restore -s upstream/master -- path/to/file
coderSam

@coderSam Чем вам за этот отзыв. Я включил ваш комментарий в ответ для большей наглядности.
VonC

8

Что вы можете сделать, это:

  1. Обновите ваш локальный репозиторий git:

    git fetch

  2. Постройте местный филиал и оформите заказ на нем:

    git branch pouet && git checkout pouet

  3. Примените коммит, который вы хотите, к этой ветке:

    git cherry-pick abcdefabcdef

    (abcdefabcdef - это sha1 коммита, который вы хотите применить)


4
Кроме того, ваш второй шаг также может быть выполнен в одной команде, как git checkout -b pouet.
Грег Хьюгилл

4
«pouet» - лучшее название ветви для этого примера.
Гусард

2

Или git stash (если у вас есть изменения) в текущей ветке, извлеките мастер, извлеките последние изменения, загрузите этот файл на рабочий стол (или во все приложение). Оформите ветку, в которой вы были. Git stash примените обратно к состоянию, в котором вы находились, затем исправьте изменения вручную или перетащите его, заменив файл.

Этот способ не очень крутой, но он работает, если вы, ребята, ничего не можете понять.


-10

Я думаю, что нашел легкий взлом.

Удалите файл, который у вас есть в локальном хранилище (файл, который вы хотите обновить с последней фиксации на удаленном сервере)

А потом сделать git pull

Поскольку файл удален, конфликта не будет


Это удаляет все возможные изменения, внесенные в этот файл локально, а также извлекает все остальные файлы, что, в частности, не хочет делать ОП.
Legrojan

Вместо обновления удаленной ветки удаление локальной - очень плохая идея.
c0der512
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.