Как я могу восстановиться после ошибочного git push -f origin master?


93

Я просто добавил неправильный источник в свой проект, используя --force option.

Можно ли вернуться? Я понимаю, что все предыдущие ветки были перезаписаны с использованием -foption, поэтому я, возможно, испортил свои предыдущие версии.


Ответы:


55

Git обычно ничего не выбрасывает, но восстановление после этого может быть непростым.

Если у вас есть правильный источник, вы можете просто вставить его в пульт с --forceопцией. Git не удалит никаких веток, если вы ему не скажете. Если вы действительно потеряли коммиты, взгляните на это полезное руководство по восстановлению коммитов . Если вы знаете SHA-1 коммитов, которые вам нужны, то, вероятно, все в порядке.

Лучшее, что можно сделать: создать резервную копию всего и посмотреть, что еще находится в вашем локальном репозитории. Если возможно, сделайте то же самое на пульте. Используйте, git fsckчтобы узнать, можете ли вы восстановить вещи, и, прежде всего, НЕ запускайтеgit gc .

Прежде всего, никогда не используйте эту --forceопцию, если вы действительно, действительно серьезно этого не понимаете.


65
Скорее всего, вы можете просто посмотреть рефлоги, чтобы определить, где изначально находились удаленные ветки. Например, git reflog show remotes/origin/master. Вы должны увидеть там свой толчок; коммит в предыдущей строке находится там, где он был до того, как вы его испортили. Затем вы можете просто отправить эту ревизию (с --force) в исходную точку и вернуться туда, где вы были!
Cascabel

@ Дэвид: Ой. Вы не упомянули в своем вопросе, что у вас нет репо. (Это, конечно, то, что вы никогда не захотите делать.) Однако, если у вас есть доступ к файловой системе, на которую вы нажали, вы все равно можете делать все это там.
Cascabel

1
@ Дэвид: Ой. Всегда хорошо иметь текущий каталог как часть вашего приглашения, чтобы избежать подобных вещей.
Cascabel

1
@Jefromi Я думаю, что то, что вы сказали, является фактическим ответом: даже со старой версией (которая не git fetchредактировалась в течение длительного времени) вы можете отобразить журнал ссылок на стороне GitHub и восстановить!
nh2

1
Где этот ответ @Jefromi? Я не вижу этого пользователя, упомянутого на этой странице, за пределами этой ветки комментариев.
Don McCurdy

47

Если вы знаете хеш фиксации, это легко, просто создайте свою ветку заново.

5794458...b459f069 master -> master (forced update)

Удалите удаленную ветку:

git push origin :master

затем воссоздайте свою ветку с помощью следующих команд:

git checkout 5794458
git branch master
git push origin master

28

Решение уже упоминалось здесь

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

Спасибо, у меня это сработало. У меня не было доступа для удаления мастера, поэтому одобренный комментарий не прошел.
Andi

Да, и git reflog show remotes/origin/masterесли необходим git reflog (как упомянуто @Cascabel выше)
Джозия Йодер

2
Это правильный ответ, спасибо за ссылку на правильный.
Noitidart

6

Если вы не находитесь в том локальном репо, откуда поступил принудительный толчок, на уровне источника / мастера нет возможности восстановить. Но если вам посчастливилось использовать GitHub или GitHub for Enterprise , вы можете взглянуть на REST API и получить потерянную фиксацию в качестве патча, например:

  1. Перечислите события и найдите формат фиксации sha1 long

https://api.github.com/repos/apache/logging-log4j2/events

  1. Загрузите потерянный коммит и получите соответствующий патч в пути json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commit/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Нанесите локально и нажмите снова

git apply patch.patch && git commit -m "восстановленная фиксация" && git push origin master


4

Другой способ восстановить потерянную фиксацию или даже выяснить, какие коммиты были потеряны, если предыдущее нажатие было получено не из вашего локального репо, - это посмотреть на вашу машину CI.

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

Машина CI может даже сохранить локальный клон репозитория, из которого вы сможете выполнить это восстановление.

Источник: вероятно, непрерывная доставка: надежные выпуски программного обеспечения с помощью автоматизации сборки, тестирования и развертывания (серия подписей Аддисона-Уэсли (Фаулер))


3

Да, вы можете восстановить коммиты после git push -f your_branch

Текст из документа :

Удалять записи старше указанного времени. Если этот параметр не указан, срок действия берется из параметра конфигурации gc.reflogExpire, который, в свою очередь, по умолчанию равен 90 дням. --expire = все записи чернослива независимо от их возраста; --expire = никогда не отключает сокращение доступных записей (но см. --expire-unreachable).

Итак, вы можете:

1- git reflog

введите описание изображения здесь

2- вы выбираете Head_Number, хотите ли вы восстановить git reset –hard HEAD@{HEAD-NUMBER}

введите описание изображения здесь

3- вы можете увидеть все коммиты в этой главе git cherry -v branch_name

4- в конце вы должны заставить толкнуть git push -f branch_name

ИЛИ

1- получить номер SHA от вашего клиента GIT (интерфейс)

git reset --hard commit_SHA

2- принудительный толчок

git push -f your_branch

Надеюсь это поможет


2

Я сделал то же самое, отменив последнее нажатие только для одного файла. Завершился возврат к исходному состоянию репозитория. Я использовал команды git от Линуса, поскольку у меня была локальная копия в Linux. К счастью, эта копия осталась нетронутой.

Все, что я сделал (после судорожного создания еще нескольких копий локального репо):

git add .
git status

(он сказал, что origin / master был впереди на 68 коммитов, хорошо ... это были все коммиты, которые я удалил)

git remote set-url origin <GIT_SSH_URL>
git push

И все вернулось так, как было до того, как я сделал сильный толчок. Самая важная вещь, о которой следует помнить, - никогда не выполнять проверку с помощью git. после того, как вы сильно толкнули. Но лучше всего отключить опцию push. Я больше никогда им не пользуюсь. Выучил урок !!


1

Для людей, находящихся в действительно плохих ситуациях, как я (например, если вы получаете bad objectошибки при работе git reset --hard):

Я написал скрипт под названием treeaver, который в крайнем случае извлекает все ваши файлы из GitHub API. Вот как им пользоваться:

  1. Клонируйте treesaverсценарий и cdк нему.
  2. Найдите SHAстроку дерева, которую вы хотите восстановить, открыв https://api.github.com/repos/<your_username_or_org>/<repo>/events .
  3. В payloadсвойстве, соответствующем вашему push-событию, найдите commitто, к чему вы хотите вернуться, и нажмите на него url.
  4. Под commit.treeскопируйте treeфайл url.
  5. Беги python3 main.py <tree_url> <path_to_save_to>.

Например, в моем случае я бы запустил:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Конечно, пиар приветствуется.


0

Здесь вы можете прочитать решения https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Второй мне помог. Я ошибся в этих командах

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

После этих команд я потерял три коммита. Чтобы восстановить их, я посмотрел на терминал, где я ошибочно сделал git pull, и увидел там вывод вроде

60223bf ... 0b258eb некоторая ветка -> происхождение / некоторая ветка

Второй хеш 0b258eb был именно тем, что мне было нужно. Итак, я взял этот хеш и произвел команду

git push --force origin 0b258eb:some-branch
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.