git pull - компактная обёртка над двумя операциями. По умолчанию
делает fetch (скачать обновления) и потом merge (слить в текущую
ветку).
Что лучше - pull или fetch + merge?
Чисто технически git pull = git fetch && git merge FETCH_HEAD.
Но многие разработчики предпочитают делать эти шаги отдельно:
git fetch- посмотреть, что пришло, не трогая локальную ветку.git log origin/main..main- проверить разницу.git mergeилиgit rebase- слить осознанно.
Это даёт паузу между «получил данные» и «изменил локальную ветку». На сложных репозиториях полезно.
--rebase vs merge
По умолчанию pull делает merge. Альтернатива - rebase:
git pull --rebase
Это значит: затащить удалённые коммиты, потом переписать твои локальные коммиты так, будто ты их сделал поверх свежих удалённых. История остаётся линейной, без merge-коммитов.
Какой вариант лучше - спор десятилетий. Прагматичное правило:
- rebase для своей feature-ветки, пока никому её не показал.
- merge для общих веток (main, master).
- Установить дефолт можно конфигом:
git config --global pull.rebase true.
Без явной настройки Git 2.27+ выдаёт warning о неоднозначности
стратегии при каждом git pull. По умолчанию pull всё равно
отрабатывает (merge), но дёргает - чтобы выбор был осознанный.
Поставь pull.rebase или pull.ff в конфиг, и предупреждение
пропадёт.
--ff-only
Самый безопасный вариант:
git pull --ff-only
Затащит обновления, только если можно fast-forward. Если у тебя локально есть несмерженные коммиты - откажет, придётся решать вручную (merge или rebase). Это предотвращает случайные merge-коммиты от инерции.
Что делает physically
git fetch origin- скачивает все новые объекты в.git/objects/и обновляетorigin/<branches>(это refs/remotes/origin/...).- Берёт remote tracking branch (
origin/main) и сравнивает с локальной (main). - Запускает merge (или rebase) FETCH_HEAD в текущую ветку.
Локальная история пишется только на шаге 3. До этого git fetch
можно вызывать сколько угодно - он безопасен.
Подводные камни
git pullс unstaged изменениями в файлах, которые меняет remote, отвалится с ошибкой. Решение - stash перед pull или закоммитить.- При отсутствии tracking-ветки
git pullбез аргументов не работает. Нужно явно:git pull origin main. git pull --rebaseна ветке с уже запушенными коммитами переписывает их SHA. Это значит, что следующий push потребует--force-with-lease. Не делай это для веток, которые видят другие люди.