Команда git fetch загружает коммиты, файлы и ссылки из удаленного репозитория в ваш локальный репозиторий. Извлеките данные с помощью команды fetch, если хотите увидеть, над чем работают остальные. Эта команда похожа на команду svn update и позволяет увидеть прогресс в центральном репозитории, но при этом не вынуждает вас выполнять слияние изменений с вашим репозиторием. Извлеченное содержимое в Git остается изолированным от имеющихся локальных данных и совершенно не влияет на локальную разработку. Чтобы переключиться на извлеченное содержимое, нужно отдельно запустить команду git checkout. Таким образом, применение команды fetch позволяет безопасно просмотреть коммиты, перед тем как интегрировать их в локальный репозиторий.

Загрузить содержимое из удаленного репозитория можно с помощью двух команд: git pull и git fetch. Из этих двух команд git fetch можно считать «безопасным» вариантом. Она загружает удаленное содержимое, но не обновляет рабочее состояние локального репозитория, оставляя текущую работу нетронутой. Команда git pull действует более агрессивно: она загружает удаленное содержимое для активной локальной ветки и сразу выполняет команду git merge, создавая коммит слияния для нового удаленного содержимого. Если у вас есть ожидающие изменения, то возникнут конфликты, и будет запущен процесс разрешения конфликтов слияния.

Как git fetch работает с удаленными ветками

Чтобы лучше понять, как работает git fetch, давайте рассмотрим, как Git организует и хранит коммиты. На самом деле все коммиты (локальные и удаленные) хранятся в каталоге ./.git/objects. Git хранит коммиты удаленных и локальных веток раздельно в виде ссылок на ветки. Ссылки на локальные ветки хранятся в каталоге ./.git/refs/heads/. При выполнении команды git branch будет выведен список ссылок на локальные ветки. Ниже приведен пример вывода команды git branch с несколькими демонстрационными именами веток.

git branch
master
feature1
debug2

Можно проверить содержимое каталога /.git/refs/heads/ — оно будет соответствовать полученному результату.

ls ./.git/refs/heads/
master
feature1
debug2

Удаленные ветки похожи на локальные, однако они сопоставляются с коммитами из репозитория другого пользователя. Удаленные ветки имеют префикс репозитория, которому принадлежат, поэтому вы не перепутаете их с локальными. Как и для локальных веток, Git также хранит ссылки на удаленные ветки. Ссылки на удаленные ветки находятся в каталоге ./.git/refs/remotes/. В следующем фрагменте кода показаны ветки, которые можно увидеть после извлечения удаленного репозитория с именем remote-repo:

git branch -r
# origin/master
# origin/feature1
# origin/debug2
# remote-repo/master
# remote-repo/other-feature

В выводе перечислены локальные ветки, показанные ранее, но теперь они отображаются с префиксом origin/. Кроме того, можно видеть удаленные ветки с префиксом remote-repo. Переключиться на удаленную ветку можно так же, как и на локальную, но при этом указатель HEAD окажется в открепленном состоянии (как при переключении на старый коммит). Вы можете расценивать такие ветки как доступные только для чтения. Чтобы просмотреть удаленные ветки, просто передайте команде git branch флаг -r.

Просмотреть удаленные ветки можно с помощью привычных команд git checkout и git log. Если вы согласны с изменениями, которые содержит удаленная ветка, ее можно слить с локальной веткой обычной командой git merge. Таким образом, в отличие от SVN, синхронизация локального репозитория с удаленным происходит в два этапа: сначала выполняется извлечение данных, а затем их слияние. Удобная короткая команда git pull выполняет сразу оба этих процесса.

Команды и опции git fetch

git fetch <remote>

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

git fetch <remote> <branch>

Аналогично команде выше, но данные извлекаются только для указанной ветки.

git fetch --all

Мощная команда, которая извлекает все зарегистрированные удаленные репозитории и их ветки.

git fetch --dry-run

Опция --dry-run выполняет демонстрационный прогон команды. Она выводит на экран действия, которые были бы выполнены при извлечении, не выполняя их на самом деле.

Примеры использования git fetch

Извлечение удаленной ветки

В следующем примере будет показано, как извлечь удаленную ветку и обновить состояние локального рабочего репозитория содержимым удаленной ветки. Для этого представим, что существует центральный репозиторий origin, с которого с помощью команды git clone был клонирован локальный репозиторий. Допустим также, что имеется дополнительный удаленный репозиторий с именем coworkers_repo, содержащий ветку feature_branch, которую нужно будет настроить и извлечь. Приняв данные условия, продолжим пример.

Сначала необходимо настроить удаленный репозиторий с помощью команды git remote.

git remote add coworkers_repo git@bitbucket.org:coworker/coworkers_repo.git

Создана ссылка на репозиторий коллеги с помощью URL‑адреса этого репозитория. Теперь передадим имя удаленного репозитория команде git fetch, чтобы загрузить его содержимое.

git fetch coworkers feature_branch
fetching coworkers/feature_branch

Теперь содержимое ветки coworkers/feature_branch представлено локально, и его нужно будет интегрировать с локальной рабочей копией. Начнем процесс с команды git checkout, чтобы переключиться на только что загруженную удаленную ветку.

git checkout coworkers/feature_branch
Note: checking out coworkers/feature_branch'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

Данный вывод команды checkout указывает на то, что указатель HEAD находится в открепленном состоянии. Такое состояние ожидаемо и означает, что ссылка HEAD указывает на ссылку, которая не соответствует локальной истории. Поскольку ссылка HEAD указывает на ссылку coworkers/feature_branch, из этой ссылки можно создать новую локальную ветку. В выводе, сообщающем об открепленном состоянии HEAD, указано, как это можно сделать с помощью команды git checkout:

git checkout -b local_feature_branch

Здесь создана новая локальная ветка с именем local_feature_branch. Теперь ссылка HEAD указывает на последнюю версию удаленного содержимого, и можно продолжать разработку, начиная с этой точки.

Синхронизация с репозиторием origin командой git fetch

В следующем примере рассматривается типичный процесс синхронизации локального репозитория с главной веткой центрального репозитория.

git fetch origin

Эта команда покажет загруженные ветки:

a1e8fb5..45e66a4 master -> origin/master
a1e8fb5..9e8ab1c develop -> origin/develop
* [new branch] some-feature -> origin/some-feature

The commits from these new remote branches are shown as squares instead of circles in the diagram below. As you can see, git fetch gives you access to the entire branch structure of another repository.

Чтобы увидеть, какие коммиты были добавлены к вышестоящей главной ветке, можно выполнить команду git log, используя origin/master в качестве фильтра:

git log --oneline master..origin/master

Чтобы подтвердить изменения и выполнить их слияние с локальной главной веткой, используйте следующие команды:

git checkout master
git log origin/master

Затем можно воспользоваться командой git merge origin/master:

git merge origin/master

Ветка origin/master и главная ветка теперь указывают на один и тот же коммит, а ваш репозиторий синхронизован с вышестоящими результатами.

Сводная информация по git fetch

Рассмотренная команда git fetch — это основная команда, которая используется для загрузки содержимого из удаленного репозитория. Чтобы обновить локальный репозиторий до состояния удаленного репозитория, команда git fetch используется в сочетании с командами git remote, git branch, git checkout и git reset. Команда git fetch представляет собой важную часть рабочих процессов, связанных с совместной работой в Git. Поведение git fetch сходно с поведением команды git pull, однако git fetch можно считать более безопасным вариантом без разрушения информации.