Олег Марков
Получение изменений в Git с помощью git fetch
Введение
Команда git fetch часто остается недооцененной, хотя именно она лежит в основе безопасной работы с удаленными репозиториями. С ее помощью вы получаете все новые коммиты и ссылки с сервера, но не меняете свое текущее состояние рабочей ветки. Это позволяет спокойно изучить изменения, сравнить их со своей работой и уже потом решать, как их интегрировать.
Смотрите, я покажу вам, как git fetch помогает отделить получение данных от слияния и почему опытные разработчики используют его ежедневно. Мы разберем не только базовый синтаксис, но и полезные флаги, типичные сценарии использования, а также то, как git fetch связан с ветками, remote-tracking ветками и тегами.
Что делает git fetch на самом деле
Локальный репозиторий и remote-tracking ветки
Чтобы понимать, что делает git fetch, важно разобраться с термином "remote-tracking ветка".
Когда вы клонируете репозиторий, Git создает:
- ваши обычные локальные ветки (например, main или develop)
- специальные ветки вида origin/main, origin/develop и т.д.
Ветки origin/main, origin/feature-x и подобные называются remote-tracking ветками. Они не для прямой разработки, а для хранения состояния веток на удаленном репозитории (обычно origin). Это как локальный "слепок" удаленных веток на момент последнего обновления.
Теперь главное: git fetch обновляет именно эти remote-tracking ветки и связанные с ними объекты (коммиты, теги), но не трогает ваши локальные ветки и рабочие файлы.
Краткое определение git fetch
Если выразить суть git fetch в одном предложении:
- git fetch скачивает из удаленного репозитория новые объекты (коммиты, ветки, теги) и обновляет ссылки origin/*, но не изменяет вашу текущую ветку и файлы в рабочем каталоге.
Это ключевое отличие от git pull, который помимо fetch сразу же пытается слить изменения в вашу текущую ветку.
Базовое использование git fetch
Самый простой вариант
Давайте разберемся на самом простом примере. Вы сидите в ветке main и хотите получить все свежие изменения с сервера origin, но пока не готовы их сливать:
# Получаем все обновления из удаленного репозитория origin
git fetch origin
Что произойдет:
- Git обратится к серверу origin
- скачает все новые коммиты, которых нет у вас локально
- обновит remote-tracking ветки, например:
- origin/main
- origin/develop
- origin/feature/login
- ваша локальная ветка main останется на своем текущем коммите
- файлы на диске не изменятся
Чтобы увидеть разницу между вашей веткой main и обновленной origin/main, вы можете выполнить:
# Показываем разницу между локальной веткой main и удаленной origin/main
git diff main..origin/main
Комментарии:
- так вы увидите, какие изменения есть на сервере, но еще не применены у вас
- ничего не сливается автоматически, вы просто смотрите разницу
git fetch без указания remote
Часто вы увидите такую форму:
# Эквивалентно git fetch origin если origin — remote по умолчанию
git fetch
Здесь Git использует удаленный репозиторий по умолчанию (обычно origin). Так можно писать, если у вас не несколько удаленных репозиториев, а один основной.
Просмотр обновленных веток после fetch
После выполнения git fetch вам полезно посмотреть, какие ветки обновились. Вот простой способ:
# Показываем локальные и remote-tracking ветки
git branch -vv
Комментарии:
- флаг -vv показывает, к какой remote-tracking ветке привязана локальная ветка и какой у нее последний коммит
- вы увидите, отстает ли ваша локальная ветка от удаленной (например, на несколько коммитов)
Отличие git fetch от git pull
Концептуальная разница
Теперь давайте разберемся, в чем практическое отличие git fetch и git pull.
git fetch:
- только скачивает изменения и обновляет origin/*
- ваша текущая ветка не меняется
- рабочие файлы не меняются
git pull:
- сначала делает git fetch
- затем автоматически выполняет слияние (merge) или перемотку (fast-forward) в текущую ветку
- может изменить ваши файлы и историю ветки
Фактически:
git pull
эквивалентно:
git fetch
git merge origin/ТЕКУЩАЯ_ВЕТКА # или git rebase в зависимости от настроек
Почему многие предпочитают сначала git fetch
Покажу вам типичный рабочий процесс в командах, где ценят контроль над историей:
# 1. Получаем свежие данные с сервера
git fetch
# 2. Смотрим, что именно изменилось
git log HEAD..origin/main --oneline
# 3. Сравниваем код до слияния
git diff HEAD..origin/main
# 4. Только после анализа — сливаем или перематываем
git merge origin/main # или git rebase origin/main
Такой подход позволяет:
- заранее увидеть, какие коммиты придут в вашу ветку
- избежать неожиданного мерджа и конфликтов "вслепую"
- принять осознанное решение — делать merge, rebase или пока ничего не трогать
Частые сценарии использования git fetch
Получить все изменения и обновить текущую ветку
Самый распространенный сценарий: вы хотите быть в актуальном состоянии относительно origin/main.
Порядок действий:
# Находимся в ветке main
git checkout main
# 1. Получаем изменения
git fetch origin
# 2. Обновляем локальную ветку main до origin/main
git merge origin/main
# или если хотите "идеальную" прямую историю:
# git rebase origin/main
Комментарии:
- после git fetch у вас есть обновленная origin/main
- merge добавит новый merge-коммит (если не fast-forward)
- rebase перепишет ваши локальные коммиты поверх origin/main
Получение изменений только для одной ветки
Иногда вам не нужны все ветки, а только одна конкретная. Для этого можно использовать более точную форму:
# Получаем только изменения ветки main из origin
git fetch origin main
Что происходит:
- Git скачает только те объекты, которые нужны для обновления origin/main
- остальные ветки в origin останутся не обновленными в вашем локальном репозитории
Получение всех веток и тегов
Если вы хотите полностью "синхронизировать" локальную копию с удаленным репозиторием (по структуре ссылок), есть смысл получить и ветки, и теги:
# Получаем все ветки и все теги
git fetch --all --tags
Комментарии:
- --all — пройтись по всем настроенным удаленным репозиториям (origin, upstream и т.д.)
- --tags — дополнительно получить все теги, даже если они не достигались по ссылкам веток
Разбор ключевых опций git fetch
--all
# Получаем обновления со всех удаленных репозиториев
git fetch --all
Когда это полезно:
- у вас настроено несколько удаленных:
- origin — ваш форк
- upstream — оригинальный репозиторий
- вы хотите сразу подтянуть изменения отовсюду
Git последовательно выполнит fetch для каждого remote.
--prune
Со временем некоторые ветки на сервере удаляются, а у вас при этом остаются старые записи origin/branch-old. Это захламляет список веток и мешает ориентироваться.
Опция --prune решает эту проблему:
# Получаем изменения и удаляем локальные remote-tracking ветки, которых уже нет на сервере
git fetch --prune
# Короткая форма
git fetch -p
Что делает --prune:
- сравнивает список веток на сервере и ваши remote-tracking ветки
- удаляет те origin/ветка, для которых нет соответствующей ветки на сервере
Вы можете включить prune по умолчанию:
# Включаем автоматический prune при каждом fetch для всех репозиториев
git config --global fetch.prune true
--tags и --no-tags
По умолчанию git fetch загружает только те теги, на которые есть ссылки из веток или явно запрашиваемых объектов. Если вам нужно забрать все теги, используйте:
# Получаем все теги с сервера origin
git fetch origin --tags
Если наоборот, вы не хотите получать теги в конкретном вызове:
git fetch origin --no-tags
Это может быть полезно в больших репозиториях с огромным количеством тегов, если вы их не используете.
--depth (shallow fetch)
Иногда нужен "облегченный" репозиторий — например, для CI/CD, где важны только последние несколько коммитов, а не вся история.
Здесь помогает параметр --depth:
# Получаем только последние 20 коммитов ветки main
git fetch origin main --depth=20
Комментарии:
- такой репозиторий называется shallow (поверхностный)
- в нем нет всей истории, поэтому некоторые команды Git будут работать ограниченно
Расширить shallow-репозиторий можно, увеличив глубину:
# Догружаем еще историю
git fetch origin --depth=100
или полностью убрав ограничение:
# Делаем репозиторий "полным" догружая всю историю
git fetch origin --unshallow
--dry-run
Если вы хотите понять, что изменится после fetch, но пока ничего не скачивать, используйте:
# Показываем что было бы обновлено, но не скачиваем
git fetch --dry-run
Git выведет список веток, которые будут обновлены, но не изменит локальный репозиторий. Это удобно, чтобы перед важным обновлением понять масштаб изменений.
Работа с несколькими удаленными репозиториями
Настройка нескольких remote
Частый сценарий — работа с форком. У вас есть:
- origin — ваш форк
- upstream — оригинальный репозиторий
Добавить второй remote можно так:
# Добавляем новый удаленный репозиторий с именем upstream
git remote add upstream https://github.com/ORIGINAL/PROJECT.git
Теперь, чтобы получить изменения из оригинального репозитория, используйте:
# Получаем изменения из upstream но не из origin
git fetch upstream
Remote-tracking ветки будут иметь вид:
- upstream/main
- upstream/develop
- и т.д.
Теперь вы увидите два набора remote-tracking веток: origin/ и upstream/.
Обновление форка через git fetch
Покажу вам типичный процесс обновления форка:
# 1. Получаем изменения из оригинального репозитория
git fetch upstream
# 2. Переходим на локальную ветку main
git checkout main
# 3. Сливаем изменения из upstream/main в наш main
git merge upstream/main
# или:
# git rebase upstream/main
# 4. Отправляем обновленную ветку в свой форк на GitHub
git push origin main
Комментарии:
- git fetch upstream ничего не меняет в вашем origin
- вы явно выбираете, какие изменения из upstream применять
Как git fetch взаимодействует с ветками
Локальные и remote-tracking ветки
Давайте посмотрим на связку локальной ветки и remote-tracking ветки на примере:
# Находимся в локальной ветке main
git checkout main
# Смотрим подробную информацию
git branch -vv
Вы увидите примерно такую строку:
* main 1234abc [origin/main] Some commit message
Комментарии:
- main — ваша локальная ветка
- origin/main — remote-tracking ветка, за которой "следит" main
- это значит, что git pull в этой ветке будет получать изменения именно из origin/main
После git fetch origin origin/main обновится, а main останется прежней. Разницу между ними легко посмотреть:
# Показывает список коммитов которых еще нет в локальной ветке main
git log main..origin/main --oneline
Ссылка FETCH_HEAD
После выполнения git fetch Git создает (или обновляет) специальную ссылку FETCH_HEAD. Она указывает на последние полученные коммиты.
Например:
# Получаем изменения
git fetch origin main
# Сливаем только что полученные изменения не ссылаясь явно на origin/main
git merge FETCH_HEAD
Комментарии:
- FETCH_HEAD удобно использовать в скриптах
- чаще всего в интерактивной работе разработчики предпочитают явно писать origin/main, так понятнее
git fetch и теги
Получение отдельных тегов
Если вам нужен конкретный тег с сервера, вы можете получить его так:
# Получаем конкретный тег v1.2.0 из origin
git fetch origin tag v1.2.0
Комментарии:
- это скачает только указанный тег и связанные с ним объекты
- удобно, если вам не нужно подтягивать все теги
Обновление всех тегов
Если вам нужны все теги, но вы не хотите обновлять ветки, можно сделать:
# Получаем только теги
git fetch origin --tags
или вместе с остальными изменениями:
# Получаем все ветки и теги
git fetch origin --tags
После этого можно, например, перейти к нужному тегу:
# Переключаемся в состояние репозитория на момент тега v1.2.0
git checkout v1.2.0
Типичные рабочие паттерны с git fetch
Ежедневное обновление перед началом работы
Многие команды рекомендуют начинать день с обновления локального репозитория:
# 1. Обновляем данные с сервера с удалением устаревших remote-tracking веток
git fetch -p
# 2. Смотрим изменения в основной ветке
git log main..origin/main --oneline
# 3. Обновляем локальную ветку main
git checkout main
git merge origin/main
# или
# git rebase origin/main
Так вы снижаете вероятность конфликтов и работаете с актуальной кодовой базой.
Проверка чужой ветки без ее локального создания
Иногда нужно посмотреть чужую ветку, не создавая сразу полноценную локальную ветку. Давайте посмотрим, как это сделать.
# Получаем все обновления из origin
git fetch origin
# Смотрим список remote-tracking веток
git branch -r
# Например нам нужна ветка origin/feature/login
git checkout origin/feature/login
Комментарии:
- git checkout origin/feature/login переведет вас в "detached HEAD" состояние
- вы можете просматривать файлы, запускать тесты, но не рекомендуется коммитить в таком состоянии
- если ветка вам нужна для разработки, создайте от нее локальную:
# Создаем локальную ветку на основе удаленной
git checkout -b feature/login origin/feature/login
Обновление фичи-ветки относительно обновленного main
Распространенный сценарий: вы разрабатываете feature/login, а в main уже появились новые коммиты. Смотрите, как аккуратно подтянуть их.
# 1. Получаем свежие изменения
git fetch origin
# 2. Обновляем локальный main
git checkout main
git merge origin/main # или git rebase origin/main
# 3. Возвращаемся в свою фичу
git checkout feature/login
# 4. Обновляем фичу относительно обновленного main
git rebase main
# или если команда предпочитает merge:
# git merge main
git fetch здесь играет роль надежного "транспортного слоя" — он доставляет вам свежую историю, а вы уже сами решаете, как ее интегрировать.
Настройка поведения git fetch через git config
fetch.prune
Как я уже показывал, очень удобно, когда устаревшие remote-tracking ветки удаляются автоматически. Чтобы включить это поведение для всех репозиториев:
# Включаем prune по умолчанию
git config --global fetch.prune true
Если нужно включить prune только для конкретного remote в одном репозитории:
# Включаем prune только для origin в текущем репозитории
git config remote.origin.prune true
fetch.recurseSubmodules
Если вы используете субмодули, то при fetch основного репозитория можно автоматически обновлять и субмодули. Для этого есть настройка:
# Включаем рекурсивный fetch для субмодулей
git config fetch.recurseSubmodules on-demand
Режимы:
- on-demand — обновлять субмодули только когда это нужно
- yes — всегда обновлять субмодули
- no — не обновлять автоматически
Настройка по умолчанию для удаленного
Часто имя origin используется по умолчанию, но если вам нужно задать другой remote по умолчанию для fetch, вы можете перенастроить:
# Меняем remote по умолчанию для fetch в текущем репозитории
git remote set-url origin https://new-url.example.com/repo.git
Remote по умолчанию определяется при клонировании, но вы можете переименовать или перенастроить его по необходимости.
Диагностика и решение проблем с git fetch
Проблемы с аутентификацией
Если git fetch выдает ошибку авторизации (401, 403 или запрос пароля бесконечно), проверьте:
- Адрес удаленного репозитория:
git remote -v
- Правильность токена или SSH-ключа
- Настройки URL:
# Меняем протокол с HTTPS на SSH (или наоборот)
git remote set-url origin git@github.com:USER/REPO.git
Конфликт имен веток и тегов
Иногда на сервере может появиться тег с тем же именем, что и ветка. Тогда git fetch может ругаться на конфликт ссылок. В этом случае:
- Сначала посмотрите, что именно конфликтует
- Переименуйте локальный тег или ветку, или удалите его, если он вам не нужен:
# Удаляем локальный тег
git tag -d v1.0.0
# Удаляем локальную ветку
git branch -d old-branch
После этого повторите git fetch.
"Не подтягиваются" новые ветки
Если после git fetch вы не видите новую ветку, которую создали коллеги, проверьте:
# Список всех remote-tracking веток
git branch -r
Если ветка есть как origin/feature/x, но у вас нет локальной ветки, ее нужно создать:
# Создаем локальную ветку на основе удаленной
git checkout -b feature/x origin/feature/x
Если же даже в списке origin/* ветки нет, возможно, на сервере ее еще не запушили.
Заключение
Команда git fetch — это основа безопасной и предсказуемой работы с удаленными репозиториями. Она аккуратно разделяет два процесса: получение данных с сервера и интеграцию этих данных в вашу рабочую ветку. Благодаря этому вы можете:
- держать локальный репозиторий в актуальном состоянии
- заранее анализировать изменения перед слиянием
- работать с несколькими удаленными репозиториями и форками
- поддерживать список веток и тегов в порядке
Давайте зафиксируем ключевые моменты:
- git fetch обновляет remote-tracking ветки (origin/, upstream/), но не трогает ваши локальные ветки и рабочие файлы
- git pull = git fetch + git merge (или rebase) для текущей ветки
- опция --prune помогает автоматически убирать устаревшие remote-tracking ветки
- с помощью git fetch удобно работать с форками и несколькими remotes
- теги можно скачивать выборочно (tag vX.Y.Z) или все сразу (--tags)
- shallow fetch (--depth) позволяет экономить место и ускорять CI, если не нужна вся история
Когда вы начнете осознанно использовать git fetch в повседневной работе, у вас появится больше контроля над историей и меньше неожиданных конфликтов и "магических" изменений после pull.
Частозадаваемые технические вопросы по теме и ответы
Что делать, если после git fetch и git merge появились конфликты
- Git сообщит, в каких файлах конфликты.
- Откройте эти файлы в редакторе и найдите конфликтные блоки с маркерами вида
<<<<<<<,=======,>>>>>>>. - Аккуратно выберите нужный вариант или объедините оба фрагмента.
- Удалите маркеры конфликтов и сохраните файл.
- Пометьте файлы как решенные:
git add путь/к/файлу
- Завершите merge:
git commit
Как отменить результаты merge после git fetch если что-то пошло не так
- Найдите предыдущий коммит перед merge:
git log --oneline
- Если merge-коммит был последним и вы хотите просто откатить ветку:
git reset --hard HEAD~1
- Если merge уже был запушен, вместо reset лучше использовать revert:
git revert -m 1 <hash_merge-коммита>
Это создаст новый коммит, отменяющий изменения merge.
Как сделать так чтобы git pull всегда делал rebase а не merge
Если вам нравится история без лишних merge-коммитов, настройте pull:
# Для всех репозиториев
git config --global pull.rebase true
# Только для текущего репозитория
git config pull.rebase true
Теперь git pull будет эквивалентен:
git fetch
git rebase origin/ТЕКУЩАЯ_ВЕТКА
Почему после git fetch --all я вижу странные remote-tracking ветки
Часто это результат того, что у вас настроено несколько remotes с разными наборами веток. Проверьте:
git remote -v
git branch -r
Если какие-то remote вам больше не нужны, удалите их:
git remote remove имя_remote
Лишние remote-tracking ветки можно почистить через:
git fetch --all --prune
Как узнать какие именно объекты скачал последний git fetch
Git хранит информацию о последнем fetch в файле .git/FETCH_HEAD. Быстрый способ посмотреть, какие ветки обновлялись:
cat .git/FETCH_HEAD
Чтобы увидеть новые коммиты относительно вашей текущей ветки:
git log HEAD..FETCH_HEAD --oneline
Так вы увидите, какие коммиты появились после последнего fetch.
Постройте личный план изучения Git до уровня Middle — бесплатно!
Git — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Git
Лучшие курсы по теме

Основы Git
Антон Ларичев
TypeScript с нуля
Антон Ларичев