Git pull и git fetch — в чём разница?

Обложка: Git pull и git fetch — в чём разница?

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

Ключевые выводы:git fetch загружает изменения с удалённого репозитория, но не трогает рабочую копию и локальные ветки — git pull = git fetch + git merge (по умолчанию) — Используйте fetch, когда хотите сначала посмотреть, что изменилось — Используйте pull, когда уверены, что конфликтов не будет — git pull --rebase — альтернатива merge, которая сохраняет линейную историю

Что делает git fetch

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

Представьте, что вы работаете в ветке main. Коллега запушил три коммита. Чтобы увидеть его изменения, не сливая их в свой код:

			git fetch origin
		

В терминале вы увидите что-то вроде:

			From github.com:team/project
   a1b2c3d..d4e5f6a  main       -> origin/main
 * [new branch]      feature/ui -> origin/feature/ui
		

После этого новые коммиты окажутся в origin/main. Это remote-tracking ветка — локальная копия удалённой ветки main. Git хранит две версии: вашу локальную main (с вашими коммитами) и origin/main (зеркало того, что на сервере). git fetch обновляет только origin/main, ваша main остаётся нетронутой. Читайте также наш полный путеводитель по Git.

Теперь можно посмотреть, что именно изменилось:

			# Какие коммиты пришли с удалённого репозитория
git log main..origin/main --oneline

# Что изменилось в файлах
git diff main origin/main

# Краткая сводка: какие файлы затронуты
git diff --stat main origin/main
		

Если изменения вас устраивают, можно слить их вручную:

			git merge origin/main
		

Получение конкретной ветки

По умолчанию git fetch origin загружает все ветки. Если нужна только одна:

			# Загрузить только ветку feature/auth
git fetch origin feature/auth

# Посмотреть её коммиты
git log origin/feature/auth --oneline -5
		

Получение всех удалённых репозиториев

Если у вас несколько remote-ов (например, origin и upstream для форка):

			# Загрузить изменения со всех remote-ов
git fetch --all

# Посмотреть список удалённых веток
git branch -r
		

Что делает git pull

git pull скачивает изменения и сразу сливает их в текущую ветку. Это удобно, но означает, что у вас не будет шанса посмотреть изменения перед слиянием.

			# Стянуть и сразу слить изменения из origin/main
git pull origin main
		

Если коллега изменил те же файлы, что и вы — git pull может привести к конфликту слияния. В этом случае git остановится и попросит вас разрешить конфликты вручную.

Пример: типичный рабочий день с git pull

			# Утром: стягиваем свежие изменения
git pull origin main

# Работаем, делаем коммиты...
git add .
git commit -m "feat: добавить валидацию формы"

# Перед пушем — снова стягиваем (вдруг кто-то запушил)
git pull origin main

# Если конфликтов нет — пушим
git push origin main
		

Что происходит при конфликте

Если git pull обнаруживает конфликт, вы увидите примерно такое:

			$ git pull origin main
Auto-merging src/utils.js
CONFLICT (content): Merge conflict in src/utils.js
Automatic merge failed; fix conflicts and then commit.
		

Откройте файл с конфликтом — внутри вы увидите маркеры:

			<<<<<<< HEAD
function validate(input) {
  return input.length > 0;
}
=======
function validate(input) {
  return input.trim().length >= 3;
}
>>>>>>> origin/main
		

Код между <<<<<<< HEAD и ======= — ваши изменения. Код между ======= и >>>>>>> origin/main — изменения с сервера. Нужно оставить правильный вариант и удалить маркеры.

Дальше:

  1. Решить, какой код оставить (или объединить оба варианта)
  2. Удалить маркеры конфликта
  3. Добавить файл в индекс: git add src/utils.js
  4. Завершить слияние: git commit

Как связаны git pull, git fetch и git merge

По умолчанию git pull — это последовательность двух команд:

			# Вот это:
git pull origin main

# Эквивалентно вот этому:
git fetch origin
git merge origin/main
		

То есть pull делает всё то же самое, что fetch + merge, но в одну команду. Разница — только в контроле: с fetch вы можете посмотреть изменения перед слиянием.

Пошаговый пример: fetch + merge vs pull

Допустим, вы работаете в ветке feature/login, а коллега запушил изменения в main. Вам нужно подтянуть эти изменения.

Вариант 1: безопасный (fetch + merge)

			# 1. Загружаем изменения, не трогая рабочую копию
git fetch origin

# 2. Смотрим, что нового в main на сервере
git log main..origin/main --oneline
# a1b2c3d Исправить баг в авторизации
# d4e5f6a Обновить зависимости

# 3. Смотрим diff, если нужно
git diff main origin/main

# 4. Переключаемся на main и сливаем удалённые изменения
git checkout main
git merge origin/main

# 5. Возвращаемся в свою ветку и подтягиваем обновлённый main
git checkout feature/login
git merge main
		

Вариант 2: быстрый (pull)

			# Всё то же самое, но в две команды
git checkout main
git pull origin main

git checkout feature/login
git merge main
		

Результат одинаковый. Но в первом варианте вы видели, какие коммиты прилетели, и могли решить — сливать или подождать. Подробнее об основах Git -- в нашей шпаргалке для начинающих.

git pull --rebase — альтернатива merge

По умолчанию git pull создаёт merge-коммит. Если вы хотите сохранить линейную историю без лишних merge-коммитов, используйте флаг --rebase:

			git pull --rebase origin main
		

Разница наглядно:

			# С обычным pull (merge):
# * a1b2c3d (HEAD) Merge branch 'main'
# |\
# | * d4e5f6a Коммит коллеги
# * | f7a8b9c Ваш коммит
# |/
# * 0c1d2e3 Общий предок

# С pull --rebase:
# * f7a8b9c (HEAD) Ваш коммит
# * d4e5f6a Коммит коллеги
# * 0c1d2e3 Общий предок
		

Если при --rebase возникнет конфликт, git остановится и предложит три варианта:

			# Разрешить конфликт и продолжить rebase
git add <файл>
git rebase --continue

# Пропустить проблемный коммит
git rebase --skip

# Отменить rebase и вернуться к исходному состоянию
git rebase --abort
		

Обратите внимание: при конфликте во время rebase для продолжения используется git rebase --continue, а не git commit, как при обычном merge. Подробнее о rebase -- в статье git rebase vs merge: когда что использовать.

Чтобы сделать --rebase поведением по умолчанию:

			# Для конкретного репозитория
git config pull.rebase true

# Глобально (для всех репозиториев)
git config --global pull.rebase true
		

Когда использовать git fetch, а когда git pull

Вот практические ориентиры:

Используйте git fetch, когда:

  • Хотите посмотреть, что изменилось, перед слиянием
  • Работаете в команде и не уверены в совместимости изменений
  • Нужно сравнить локальную и удалённую ветки
  • Пишете скрипты для CI/CD — fetch безопаснее, потому что не меняет рабочее дерево

Используйте git pull, когда:

  • Работаете один или изменения точно не конфликтуют
  • Утром начинаете работу и хотите быстро обновить ветку
  • Работаете с чистой веткой без локальных изменений

Полезные команды для работы с fetch и pull

			# Посмотреть, какие ветки отстали от remote
git fetch origin
git branch -vv

# Удалить локальные ссылки на удалённые ветки,
# которых больше нет на сервере
git fetch --prune

# Стянуть изменения, временно убрав незакоммиченные правки
# (автоматический git stash перед pull и git stash pop после)
git pull --autostash

# Посмотреть, что придёт с pull (dry run)
git fetch origin
git diff --stat HEAD origin/main
		

Частые вопросы про git fetch и git pull

В чём разница между git fetch и git pull?

git fetch загружает новые коммиты из удалённого репозитория в remote-tracking ветки (например, origin/main), но не трогает вашу рабочую копию и локальные ветки. git pull делает то же самое, но сразу сливает загруженные изменения в текущую ветку через git merge. Если вам важно сначала посмотреть, что изменилось — используйте fetch.

Можно ли отменить git pull?

Да. Если слияние ещё не завершено (например, вы в процессе разрешения конфликта), используйте:

			git merge --abort
		

Если git pull уже завершился и вы хотите откатиться — найдите нужную точку в reflog:

			# Посмотреть историю перемещений HEAD
git reflog

# Найти строку вида "pull: Merge" — предыдущая запись
# это состояние до pull. Откатиться к ней:
git reset --hard HEAD@{1}
		

Внимание: git reset --hard удаляет все незакоммиченные изменения в рабочей копии. Перед откатом убедитесь, что у вас нет несохранённых правок, или сделайте git stash.

Чем git fetch отличается от git clone?

git clone создаёт новую локальную копию удалённого репозитория целиком — со всей историей коммитов, ветками и настройками. Это делается один раз в начале работы с проектом. git fetch работает в уже существующем репозитории и только подтягивает свежие изменения, которые появились на сервере после последней синхронизации.

Безопасен ли git fetch?

Да. git fetch обновляет только remote-tracking ветки (origin/main, origin/feature/...) и объектную базу репозитория. Он не трогает ваши локальные ветки, рабочую копию и индекс — поэтому его можно запускать в любой момент без риска сломать текущую работу.

Что лучше: pull --rebase или pull с merge?

--rebase перебазирует ваши локальные коммиты поверх свежих с сервера, что даёт линейную историю без merge-коммитов — её удобнее читать и ревьюить. Обычный merge сохраняет точную хронологию ветвления, что может быть важно для аудита. Для большинства проектов --rebase предпочтительнее — если в вашей команде нет других договорённостей.

Итоги

Разница между git fetch и git pull — в степени контроля:

  • git fetch — загружает изменения, но не применяет их. Вы решаете, что делать дальше
  • git pull — загружает и сразу сливает. Быстро, но без возможности предварительного обзора
  • git pull --rebase — загружает и перебазирует ваши коммиты поверх свежих. Чистая линейная история

Если не уверены — начинайте с git fetch. Это безопасная команда, которая ничего не сломает. А когда убедитесь, что изменения вас устраивают — слейте их вручную через git merge.

Подробнее о работе с Git — в официальной документации git fetch и git pull, а также в нашем руководстве по Git для начинающих.