Table of Contents

Команда fetch позволяет получить информацию с удаленного репозитория, например получить новые ветки, теги и уже после получить содержимое.

Почему нужен fetch

Если на удаленном репозитории появилась новая ветка, локально мы об этом не знаем. Для обновления информации о новых ветках, коммитах, тегах в локальном репозитории используется fetch.

Часто это происходит неявно, если используется IDE или git клиент. Но попробуйте локально переключится на удаленную ветку - ничего не выйдет, пока не выполнится fetch.

Примеры работы с fetch

В примере наглядно демонстрируется состояние удаленного и локального репозитория.

Начнем с клонирования репозитория

В нашем случае в удаленном репе одна ветка main. Локально еще не получили репозиторий.

remote          local
 |-main             

Клонируем репозиторий и локально получаем главную ветку по-умолчанию:

remote          local
 |-main        |-main      

После этого, другой разработчик написал код в новой ветки:

remote          local
 |-main        |-main
 |-feat-1      

Локально мы не знаем об этой ветки, это можно проверить выполнив команду просмотра локальных веток git branch и получить:

* main

Все верно, локально у нас одна ветка и мы находимся на ней, о чем говорит *. Хотя в удаленном репозитории две ветки. Даже если мы посмотрим список удаленных веток командой git branch -r, получим:

origin/HEAD -> origin/main
origin/main

Мы снова получим только состояние репозиторий в момент клонирования, ведь это локальные данные. И если мы попробуем переключиться на ветку feat-1 - у нас ничего не выйдет git checkout feat-1:

error: pathspec 'feat-1' did not match any file(s) known to git

Так давайте получим свежие данные из репозитория.

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

После выполнения команды git fetch получим вывод:

From gitlab.com:sendel/fetch-ex
 * [new branch]      feat-1     -> origin/feat-1

Мы получили информацию о новое ветку в удаленном репозитории. Сейчас состояние репозиториев выглядит так:

remote          local
 |-main        |-main
 |-feat-1      |- 👻 feat-1     

Информация есть о удаленной ветки есть, но не зря она как приведение. Локально этой ветки еще не существует. Команда git branch -r выведет новую ветку, а список локальных git branch так и останется содержать одну main.

При этом, мы можем переключится на ветку feat-1, будет создана локальная ветка и она будет указывать на feat-1 ветку удаленного репозитория. Выполним команду перехода на ветку feat-1 git checkout feat-1:

Branch 'feat-1' set up to track remote branch 'feat-1' from 'origin'.
Switched to a new branch 'feat-1'

Теперь локально создалась ветка feat-1 и связалась с удаленной веткой feat-1.

remote          local
 |-main        |-main
 |-feat-1      |-feat-1     

Проверить можем командой git branch -a, таким образом получим список всех веток, как локальных, так и удаленных:

* feat-1
  main
  remotes/origin/HEAD -> origin/main
  remotes/origin/feat-1
  remotes/origin/main

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

А как же pull?

При выполнении команды git pull, вызывается fetch и далее уже полученные данные сливаются с выбранной веткой.

Это можно легко проверить, если вызвать git pull -v, параметр v (verbose) выводит подробную информацию о ходе выполнения команды:

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 287 bytes | 95.00 KiB/s, done.
From gitlab.com:sendel/fetch-ex
   e033308..4bbebd7  feat-2     -> origin/feat-2
 = [up to date]      feat-1     -> origin/feat-1
 = [up to date]      main       -> origin/main
Updating e033308..4bbebd7
Fast-forward
 feat-2 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Первой выполняется fetch, и далее уже слияние.

Вот такая она - призрачная команда, без которой не обойтись 👻