Git: Как игнорировать ускоренную перемотку вперед и вернуть origin [branch] для более ранней фиксации? - PullRequest
8 голосов
/ 02 июля 2010

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

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

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

 ! [rejected]        branch -> branch (non-fast-forward)
error: failed to push some refs to 'git@github.com: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.

Ответы [ 2 ]

26 голосов
/ 29 августа 2013

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

git push --force-with-lease

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

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

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

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

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

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

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

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

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

"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: исправить отчет о состоянии ссылки для --force-with-lease

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


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

18 голосов
/ 02 июля 2010

Вы можете попробовать git push --force, чтобы форсировать толчок.

--force

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

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

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

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

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

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

...