git push --force: переписать историю на сервере
Обновлено 31 июля 2026 г.
git push --force заменяет серверную ветку твоей локальной версией, даже если коммиты, которые лежали на сервере, после этого станут недостижимы.
Обычный git push умеет только надстраивать историю поверх той, что уже есть. Как только твоя версия расходится с серверной, отправка отвергается:
$ git push
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:username/my-project.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.По делу force нужен в одном случае: ты переписал собственную ветку, которую уже отправлял. После git commit --amend или git rebase коммиты новые, с другими хешами, и обычному push не за что зацепиться. Тогда отправка проходит так:
$ git push --force-with-lease
To github.com:username/my-project.git
+ 6d6699c...4e39190 main -> main (forced update)Что видит человек по ту сторону
Тот, кто успел забрать старую версию, остаётся с историей, которой на сервере больше нет. Его следующий git pull не обновляет ветку, а сшивает две расходящиеся:
$ git pull
From github.com:team/proj
+ 6d6699c...4e39190 main -> origin/main (forced update)
Merge made by the 'ort' strategy.
$ git log --oneline --graph
* d784901 Merge branch 'main' of github.com:team/proj
|\
| * 4e39190 add the hiring section
* | 6d6699c add the hiring sectoin
|/
* 470601c first version of the reportИсправленная опечатка вернулась в историю вместе с исправлением. На одном коммите это смешно, на переписанной ветке из двадцати коммитов это полдня разбора завалов у каждого, кто её забирал. Отсюда правило: force push идёт только в твою ветку, которую никто не тянул. В main и другие общие ветки - никогда.
--force-with-lease
Эта форма сначала проверяет, что на сервере всё так, как ты думаешь. Git помнит, где серверная ветка была в момент твоего последнего обмена: это указатель origin/main. Перед отправкой --force-with-lease сверяет серверную ветку с этим указателем. Совпало - переписывает, значит, с тех пор туда никто не писал. Не совпало - отказывает:
$ git push --force-with-lease
! [rejected] main -> main (stale info)
error: failed to push some refs to 'github.com:team/proj.git'stale info значит «твои сведения о сервере устарели». Сделай git fetch, посмотри, что там появилось, и решай уже с открытыми глазами. Ровно поэтому не стоит делать fetch вслепую прямо перед force push: он обновит указатель и снимет всю защиту.
Частые ошибки
Ответить флагом --force на отказ с пометкой (fetch first). Так git отвечает, когда на сервере лежат чужие коммиты, которых у тебя нет, и лечится это связкой git pull, потом git push. Force тут просто сотрёт чужую работу.
Если force push в общую ветку уже случился, коммиты никуда не делись. У любого, кто ещё не делал pull, старая история цела: он находит хеш в git reflog и возвращает ветку на место.
$ git reflog
6d6699c HEAD@{0}: clone: from github.com:team/proj.git
$ git push --force origin 6d6699c:main
To github.com:team/proj.git
+ 4e39190...6d6699c 6d6699c -> main (forced update)