Команда git fetch загружает коммиты, файлы и ссылки из удаленного репозитория в ваш локальный репозиторий. Извлеките данные с помощью команды fetch, если хотите увидеть, над чем работают остальные. Эта команда похожа на команду svn update и позволяет увидеть прогресс в центральном репозитории, но при этом не вынуждает вас делать слияние изменений с вашим репозиторием. Извлеченное содержимое остается изолированным от имеющихся локальных данных, и оно совершенно не влияет на вашу локальную разработку. Чтобы переключиться к извлеченному содержимому, нужно отдельно запустить команду 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 окажется в отсоединенном (detached) состоянии (как при переключении на старый коммит). Вы можете думать о них как о ветках, доступных только для чтения. Чтобы просмотреть список удаленных веток, просто укажите в команде git branch флаг -r.

Просмотреть удаленные ветки можно с помощью привычных команд git checkout и git log. Если вы согласны с изменениями, которые содержит удаленная ветка, их можно слить в локальную ветку обычной командой git merge. Таким образом, в отличие от SVN, синхронизация локального репозитория с удаленным репозиторием на самом деле выполняется в два этапа: сначала выполняется извлечение данных (fetch), затем их слияние (merge). Команда 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 находится в отсоединенном (detached) состоянии. Такое состояние ожидаемо и означает, что наша ссылка HEAD указывает на ссылку, которая не соответствует нашей локальной истории. Поскольку HEAD указывает на ссылку coworkers/feature_branch, мы можем создать из этой ссылки новую локальную ветку. В выводе «detached 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

На рисунке ниже коммиты из новых удаленных веток показаны не в виде кругов, а в виде квадратов. Как вы можете видеть, команда git fetch предоставляет доступ ко всей структуре веток другого репозитория.

Чтобы увидеть, какие коммиты были добавлены к вышестоящей главной ветке, можно выполнить команду 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 можно считать более безопасным, недеструктивным вариантом.