Git: Как проигнорировать перемотку вперед и вернуть origin [branch] к более раннему коммиту?

Я использовал

git reset --hard dc082bc... 
вернуться к ветви обратно в требуемое предыдущее состояние из-за некоторых неудачных фиксаций. Это перемотало мой местный филиал в порядке. Тем не менее, я хочу перемотать ветку 'origin' к тому же коммиту, чтобы я мог начать заново. Может кто-нибудь сказать мне, как вернуть исходную ветвь (не master) для этого коммита?

Я пробовал git push origin master, но выдает следующую ошибку

! [отклонено] ветвь -> ветвь (без ускоренной перемотки вперед)
ошибка: не удалось отправить некоторые ссылки на "git@github.com:xxx/xxx.git"
Чтобы предотвратить потерю истории, обновления без ускоренной пересылки были отклонены
Объедините удаленные изменения перед повторным нажатием. Смотрите "Примечание о
раздел "Перемотка вперед" в git push --help для деталей.

2 ответа

Решение

Ты можешь попробовать git push --force заставить толчок.

--force

Обычно команда отказывается обновлять удаленную ссылку, которая не является предком локальной ссылки, используемой для ее перезаписи. Этот флаг отключает проверку.
Это может привести к потере коммитов удаленным репозиторием; используйте это с осторожностью.

Так что, если многие люди уже вытащили одну и ту же ветку из источника, это может вызвать проблемы с перебазировкой на их стороне.
Эта операция может быть заблокирована на стороне сервера, как указывает ebneter (в комментариях):

Однако, в зависимости от того, как настроен пульт, это может не сработать
- все мои центральные репозитории настроены с receive.denyNonFastForwards = true а также receive.denyDeletes = true, в этом случае любая такая операция должна быть сделана на удаленном сервере.

Однако в случае с GitHub такие настройки не всегда доступны для пользователя, управляющего его репозиторием GitHub.
Так что если вы git push --force по ошибке все, что вам осталось, - это открыть дело для поддержки GitHub, чтобы они проверили свои локальные (т.е. "GitHub") рефлоги и посмотрели, могут ли они восстановить старые коммиты.
(Поскольку reflogs являются локальными, как я недавно вспомнил. Поэтому коммиты, которые заменяются новыми во время push --force только еще видны, если нет git gc ' или же ' git prune уже на стороне сервера GitHub)

Итак, Marco Ceppi настаивает (в комментариях):

это может действительно испортить локальные репозитории других участников, если вы заставляете толчки - хотя иногда это просто необходимое зло (возможно, мне приходилось делать это два раза в моей жизни с использованием Git)

Чтобы добавить к моему предыдущему ответу, и рассмотреть тот факт, что вынужденный git push может действительно испортить локальные репозитории других участников, git 1.8.5 (предстоящий 4 квартал 2013 г.) увидит новую опцию:

git push --force-with-lease

Смотрите происхождение этой опции в этой теме:

если что-то случится в origin "В ветке, которую вы заставляете или удаляете с тех пор, как выбрали ее для проверки, вы можете потерять работу других людей.

Кто-то, кто не знает о решении перемотать и перестроить ветку, может попытаться нажать на ветку между временем, которое вы выбрали, чтобы перебазировать его, и временем, которое вы подтолкнули, чтобы заменить его результатом перебазировки.

Мы можем make these pushes safer опционально позволяя пользователю сказать " git push " этот:

Я заставляю / удаляю, исходя из предположения, что значение 'branch' все еще находится в этом объекте.
Если это предположение больше не выполняется, то есть, если что-то случилось с веткой с тех пор, как я начал готовиться к этому пушу, не продолжайте и провалите этот пуш.

Вы можете увидеть полную документацию --force-with-lease в коммите 28f5d17

--force-with-lease будет защищать все удаленные ссылки, которые будут обновлены, требуя, чтобы их текущее значение было таким же, как некоторые разумные значения по умолчанию, если не указано иное;

На данный момент "некоторое разумное значение по умолчанию" предварительно определено как "значение ветви удаленного отслеживания, которую мы имеем для ссылки на обновляемый удаленный", и это ошибка, если у нас нет такой ветви удаленного отслеживания.

Это объясняет "аренду" часть этого варианта:

" force-with-lease Msgstr ": Вы предполагаете, что взяли в аренду аренду рефери, когда выбирали, чтобы решить, какой должна быть перебазированная история, и вы можете откатиться назад, только если аренда не была нарушена.


Это уже проверяется и упоминается в разделе " Что готовит в git.git (Aug 2013, # 07; Wed, 28) ":

Кстати, толчок, который переопределяет обычное "перемотка вперед", был сделан с помощью " force-with-lease "Вариант, который готовил в next, вот так:

$ git fetch ko next
$ anchor=$(git rev-parse --verify FETCH_HEAD)
$ for remote in ko repo gph github2
  do
    git push --force-with-lease=refs/heads/next:$anchor $remote next
  done

Заметка: " git push --force-with-lease "научили сообщать, нужно ли форсировать толчок (или быстро пересылать).

Итак, эта команда более подробно представлена ​​в выходных данных git 2.8 (март 2016 г.)

push: исправить отчет о статусе ссылки для --force-with-lease

--force--with-lease опция push приводит к менее подробной информации о статусе, чем --force,
В частности, выходные данные указывают, что ссылка была быстро передана, даже когда она была принудительно обновлена.


Остерегайтесь игнорирования / игнорирования этого параметра, как описано в Git 2.13 (2-й квартал 2017 года).

git reset && git push с принудительной перезаписью

# master commit uid
$ git reset --hard b9e3f7f2f66674901b467183dd81d493e50677f5

# git push branch_name --force

# local master
$ git push origin master --force

# remote master
$ git push origin/master -f

реф.

В чем разница между origin/master и origin master в Git?

https://git-scm.com/docs/git-reset

Другие вопросы по тегам