Git: Как игнорировать ускоренную перемотку вперед и вернуть начало [ветку] до более раннего фиксации?

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

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

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

 ! [rejected]        branch -> branch (non-fast-forward)
error: failed to push some refs to '[email protected]:xxx/xxx.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

Ответ 1

Вы можете попробовать git push --force принудительно нажать.

--force

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

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

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

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

Итак Марко Чеппи настаивает (в комментариях):

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

Ответ 2

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

git push --force-with-lease

См. начало этой опции в этот поток:

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

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

Мы можем make these pushes safer, необязательно позволяя пользователю сообщать "git push" следующее:

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

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

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

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

Это объясняет часть "аренды" этого параметра:

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


Это уже тестируется и упоминается в Что готовит в git.git(август 2013, № 07, ср, 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: исправить отчет о статусе ref для --force-with-lease

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


Остерегайтесь того, что этот параметр игнорируется/обойден, как объясняется в git 2.13 (Q2 2017).