Как отменить "git push -mirror"?

В проекте git/github я работаю над веткой. После нажатия он сказал следующее:

git push
To [email protected]:...
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:...'
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.

Я попытался исправить эту проблему, и после Google Google я придумал эту строку:

git push --mirror

Я выпустил следующую команду, и теперь кажется, что я удалил много ветвей с сервера.

Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:...
 - [deleted]         develop
 + 797beee...bafbc50 master -> master (forced update)
 - [deleted]         milestone
 - [deleted]         robot
 - [deleted]         strategy
 * [new branch]      origin/HEAD -> origin/HEAD
 * [new branch]      origin/develop -> origin/develop
 * [new branch]      origin/master -> origin/master
 * [new branch]      origin/milestone -> origin/milestone
 * [new branch]      origin/robot -> origin/robot
 * [new branch]      origin/robot_simulator -> origin/robot_simulator
 * [new branch]      origin/strategy -> origin/strategy
 * [new branch]      origin/vision -> origin/vision

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

Ответ 1

Вы нажали на целевую цель по умолчанию, git @github.com. Это означает, что git @github.com был удаленным в вашем исходном репо.

Это означает, что refs, удаленные с сервера, все равно будут находиться на удаленном месте после нажатия. Не обновлять пульты (!).

Подтвердите это, выполнив

git branch -a

на стороне, с которой вы нажали (локальный).

Вероятно, будут показаны ссылки, удаленные с удаленного сервера.

[продолжение следует]

Вы можете сделать что-то вроде:

for-each-ref refs/remotes/origin | while read sha type name
do 
    git branch "rescue_$(basename "$name")" "$sha"
done

для восстановления ветвей локально. Они будут называться с префиксом rescue_ в качестве меры предосторожности (в случае, если вы получите смешные или противоречивые имена ссылок).

Замените origin именем удаленного устройства


Тест script

Если вы хотите протестировать процедуру в контролируемой среде, вот мой подход сведен к минимальным шагам (выполняется в пустом каталоге, например, /tmp/work )

git init A; (cd A; touch test; git add test; git commit -m initial; git branch test1; git branch test2; git branch test3)
git clone A B
(cd B; git push --mirror origin; git branch -a)
cd A
git for-each-ref refs/remotes/origin | while read sha type name; do git branch "rescue_$(basename "$name")" "$sha"; done
git branch -a

Обратите внимание, как в этой версии я подключился к A - это было бы вашим реестром github. Вы могли бы git clone --mirror [email protected]:... local_rescue, чтобы получить подходящую локальную версию.

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

Ответ 2

Вы были в такой ситуации:

- x - A - B - C (origin/master)
   \
    D - E - F (master)

Вы хотели сделать одну из двух вещей, обе из которых описаны в документации, которую Git предложил вам прочитать:

  • Потяните, затем нажмите, давая вам следующее:

    - x - A - B - C
       \           \
        D - E - F - M (master, origin/master)
    
  • Принудительное нажатие (git push --force), дающее вам следующее:

    - x - D - E - F (master, origin/master)
    

Вместо этого с git push --mirror вы в основном сделали эквивалент принудительного нажатия всего, превратив удаленный репозиторий в зеркало вашего локального. Это означает, что, как и сообщалось, удаление всего на удаленном компьютере, которое не было в вашем репозитории.

Изменить: в ответе описывается, как восстановить. Если вы запустили git remote update, который удалил бы удаленные ветки, которые он использует для восстановления, тогда может быть полезно следующее. В противном случае вы все настроены.

Лучше всего найти кого-то, кто клонировал из удаленного репозитория (или, если вам повезет, отдельный клон, который вы сделали), скажите им не вытащить/извлечь/удаленное обновление и следуйте инструкциям из этого репо.

В противном случае восстановление будет действительно сложным. Если вы недавно общались с какой-либо из отдаленных веток, возможно, в HEAD reflog будут следы:

git reflog show

В противном случае, если удаленные ссылки ссылаются на коммиты, которые являются предками любых оставшихся ветвей, вы можете, возможно, быстро их воссоздать. Если они относятся к вещам, которые не являются предками оставшихся ветвей, вы можете найти оборванные коммиты:

git fsck

и, возможно, выясните, какие из них указали на них.