Обработка отклонённых push-запросов
Когда вы пытаетесь выполнить push, а кто-то другой уже отправил новые коммиты в ту же ветку, Git отклонит ваш push. Это одна из самых распространённых ситуаций при совместной работе — и она легко решается.
Почему push отклоняется
Git требует, чтобы ваш push был fast-forward — то есть история ветки в удалённом репозитории должна быть прямым предком вашей локальной ветки. Если в удалённом репозитории есть коммиты, которых у вас нет, push перезаписал бы их.
Ваша локальная: A --- B --- C (main)
Удалённая: A --- B --- D (origin/main)
Вы пытаетесь отправить C, но в удалённом репозитории уже есть D. Git отказывает:
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
Решение: pull, затем push
Стандартный рабочий процесс прост:
- Pull — получить удалённые изменения
- Разрешить конфликты, если они есть
- Push снова
git pull origin main
# разрешите конфликты, если нужно
git push origin main
Что происходит во время pull
Когда вы делаете pull, Git сливает удалённые изменения в вашу ветку:
До pull:
локальная: A --- B --- C (main)
удалённая: A --- B --- D (origin/main)
После pull (merge):
локальная: A --- B --- C --- M (main)
\ /
--- D ---
Теперь ваша ветка включает и C, и D, и push завершится успешно.
Pull с rebase (более чистая история)
Вместо создания коммита слияния можно перебазировать вашу работу поверх удалённых изменений:
git pull --rebase origin main
Это воспроизводит ваши коммиты после коммитов удалённого репозитория:
До:
локальная: A --- B --- C (main)
удалённая: A --- B --- D (origin/main)
После pull --rebase:
локальная: A --- B --- D --- C' (main)
Результат — чистая линейная история без коммита слияния.
Попробуйте!
Смоделируйте и разрешите отклонение push:
- Проверьте текущее состояние:
git log --oneline - Попробуйте отправить (может не получиться, если удалённый репозиторий впереди):
git push origin main - Если отклонено, сначала получите изменения:
git pull origin main - Проверьте, что слияние прошло успешно:
git log --oneline --graph - Отправьте снова:
git push origin main - Убедитесь в успехе:
git log --oneline
Как избежать конфликтов при push
- Делайте pull перед началом работы — Начинайте каждую сессию с
git pull - Отправляйте чаще — Небольшие, частые push уменьшают вероятность конфликтов
- Общайтесь — Сообщайте коллегам, когда работаете с общими файлами
- Используйте feature-ветки — Работайте в отдельных ветках, чтобы не мешать друг другу
Никогда не используйте force push (если не знаете, что делаете)
Может возникнуть соблазн использовать git push --force. Это перезаписывает историю удалённого репозитория и может уничтожить работу ваших коллег. Используйте только для веток, где вы единственный участник, и даже тогда предпочитайте --force-with-lease, который проверяет, что удалённый репозиторий не изменился с момента последнего fetch.