Можно ли восстановить ветку после ее удаления в Git? - PullRequest
925 голосов
/ 04 сентября 2010

Если я запускаю git branch -d XYZ, есть ли способ восстановить ветку?Есть ли способ вернуться, как будто я не запускал команду удаления ветки?

Ответы [ 17 ]

1682 голосов
/ 04 сентября 2010

Да, вы должны быть в состоянии сделать git reflog и найти SHA1 для коммита в конце вашей удаленной ветви, а затем просто git checkout [sha]. И как только вы получите этот коммит, вы можете просто git checkout -b [branchname] воссоздать ветку оттуда.


Кредит @Cascabel за эту сокращенную / однострочную версию.

Вы можете сделать это за один шаг:

git checkout -b <branch> <sha>
128 голосов
/ 10 марта 2014

Большую часть времени недоступные коммиты находятся в reflog. Итак, первое, что нужно попробовать, это посмотреть reflog с помощью команды git reflog (которая отображает reflog для HEAD).

Возможно, что-то проще, если коммит был частью определенной ветки, которая еще существует, - это использовать команду git reflog name-of-my-branch. Это работает также с пультом, например, если вы принудительно нажали.


Если ваши коммиты отсутствуют в вашем reflog (возможно, из-за того, что они были удалены сторонним инструментом, который не пишет в reflog), я успешно восстановил ветку, переустроив свою ветку в шаре коммит найден с помощью такой команды (он создает файл со всеми висячими коммитами):

git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

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

git config --global alias.rescue '!git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt'

и используйте его с git rescue

Чтобы исследовать найденные коммиты, вы можете отобразить каждый коммит, используя некоторые команды для их просмотра.

Чтобы отобразить метаданные фиксации (автор, дата создания и сообщение фиксации):

git cat-file -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Чтобы увидеть также различия:

git log -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Как только вы нашли свой коммит, создайте ветку для этого коммита с помощью:

git branch commit_rescued 48540dfa438ad8e442b18e57a5a255c0ecad0560
40 голосов
/ 02 июня 2015

Если вы хотите использовать графический интерфейс, вы можете выполнить всю операцию с помощью gitk.

gitk --reflog

Это позволит вам увидеть историю коммитов ветки, как если бы ветка не была удалена. Теперь просто щелкните правой кнопкой мыши на последнем коммите в ветке и выберите пункт меню Create new branch.

18 голосов
/ 08 апреля 2015

Решение, получившее наибольшее количество голосов, на самом деле делает больше, чем запрошено:

git checkout <sha>
git checkout -b <branch>

или

git checkout -b <branch> <sha>

перемещает вас в новую ветку вместе со всеми последними изменениями, которые вы, возможно, забыли зафиксировать.Это не может быть вашим намерением, особенно в «режиме паники» после потери ветки.

A Более чистое (и более простое) решение кажется однострочным (после того, как вы нашли<sha> с git reflog):

git branch <branch> <sha>

Теперь ни ваша текущая ветвь, ни внесенные изменения не затрагиваются.Вместо этого будет создана только новая ветвь вплоть до <sha>.

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

Наконец, вы можете переименовать успешно восстановленную ветку в то, что она была названа или что-нибудь еще:

git branch -m <restored branch> <final branch>

Само собой разумеется, ключчтобы успех состоял в том, чтобы найти правильный коммит <sha>, поэтому называйте свои коммиты мудро:)

14 голосов
/ 06 сентября 2010

Добавление к tfe ответ : есть также сценарий git-resurrect.sh в области contrib/Источники Git (в репозитории git.git), которые могут вам помочь.

git-resurrect <name> пытается найти следы кончика ветви с именем <name> и пытается воскресить его.В настоящее время в reflog выполняется поиск сообщений извлечения, а с -r также объединяются сообщения.С -m и -t история всех ссылок сканируется для Merge <name> into other / Merge <other> into <name> (соответственно) фиксации тем, что довольно медленно, но позволяет воскрешать ветки тем других людей.

9 голосов
/ 26 августа 2016

Для GitHub пользователей без установленного Git:

Если вы хотите восстановить его с веб-сайта GitHub , вы можете использовать их API , чтобы получить список событий, связанных с репо:

Первый

Следующая

  • перейдите на GitHub и создайте новую временную ветку, которая будет удалена навсегда ( Chrome предпочтительнее).

• Перейдите в филиалы и удалите этот.

На той же странице, без перезагрузки , откройте DevTools, панель «Сеть». Теперь приготовьтесь ...

• Нажмите восстановить. Вы заметите новую «линию». Щелкните правой кнопкой мыши по нему, выберите «Копировать как cURL» и сохраните этот текст в каком-нибудь редакторе.

• Добавить в конец скопированной строки кода: -H "Cookie=".

Теперь вы должны получить что-то вроде:

    curl 'https://github.com/UserName/ProjectName/branches?branch=BranchSHA&name=BranchName' -H 'Cookie:' -H 'Origin: https://github.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US' -H 'User-Agent: User-Agent' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: https://github.com/UserName/ProjectName/branches' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=token' --compressed

Последний шаг

  • замените "BranchSHA" вашим SHA-хешем и BranchName с желаемым именем (кстати, отличный способ переименовать ветку из сети). Если вы не слишком медлительны, вам все равно нужно сделать этот запрос. Например, просто скопируйте и вставьте в терминал.

приписка

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

9 голосов
/ 13 мая 2013

Если у вас нет рефлога, например.поскольку вы работаете в пустом репозитории, в котором не включен reflog, а коммит, который вы хотите восстановить, был создан недавно, другой вариант - найти недавно созданные объекты коммитов и просмотреть их.

Изнутри.git/objects запуск каталога:

find . -ctime -12h -type f | sed 's/[./]//g' | git cat-file --batch-check | grep commit

Находит все объекты (коммиты, файлы, теги и т. Д.), Созданные за последние 12 часов, и фильтрует их, чтобы показать только коммиты.Проверка их - это быстрый процесс.

Сначала я попробую скрипт git-ressurect.sh, упомянутый в Ответ Якуба .

8 голосов
/ 14 ноября 2016

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

$ git fsck --full --no-reflogs --unreachable --lost-found > lost
$ cat lost | cut -d\  -f3 > commits
$ cat commits | xargs -n 1 git log -n 1 --pretty=oneline

Теперь найдите git commit id (GIT-SHA) на основе комментариев коммита и используйте его в приведенной ниже команде. Оформить заказ на новую ветку под названием NEW-BRANCH с ранее найденным GIT-SHA:

$ git checkout -b NEW-BRANCH GIT-SHA
7 голосов
/ 12 августа 2012

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

git branch -d [branch]

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

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

git branch -D [branch]

Это часть обязательного просмотра видео от Скотта Чакона о Git. Проверьте минуты 58:00, когда он говорит о ветках и как их удалить.

Введение в Git со Скоттом Чаконом из GitHub

4 голосов
/ 23 февраля 2016

Чтобы восстановить удаленную ветку, сначала просмотрите историю рефлогов,

git reflog -n 60

Где n относится к последним n коммитам. Затем найдите подходящую голову и создайте ветку с этой головой.

git branch testbranch HEAD@{30}
...