Чи можу я відновити гілку після її видалення в Git?


1066

Якщо я біжу git branch -d XYZ, чи є спосіб відновити гілку? Чи є спосіб повернутися так, ніби я не запустив команду видалити гілку?


4
Справді приголомшлива примітка щодо прийнятої відповіді полягає в тому, що вона працює, навіть якщо гілка була видалена за походженням! Я просто відновив кілька гілок, яких у мене вже не було на місцях, після того, як вони були випадково видалені за походженням.
theblang

Відповіді:


1955

Так, ви повинні мати змогу зробити git reflogі знайти SHA1 для фіксації на кінчику видаленої гілки, а потім просто git checkout [sha]. І як тільки ви перейдете на цю комісію, ви зможете просто git checkout -b [branchname]відтворити гілку звідти.


Заслуга @Cascabel для цієї конденсованої / однолінійної версії.

Це можна зробити за один крок:

git checkout -b <branch> <sha>

477
Ви можете зробити це в один крок: git checkout -b <branch> <sha>.
Каскабель

200
Коротка порада - якщо ви тільки що видалили гілку, ви побачите щось подібне у своєму терміналі - "Видалене відділення <ваш- галузь> (було <sha>)". І тоді це дуже просто - просто використовуйте це <sha>. Наприклад, як згадувалося вище -git checkout -b <branch> <sha>
Сніговий удар

6
так, просто прокрутіть угору у своєму терміналі (якщо ви цього не зробили CMD+K)
неаумузичний

42
Використовуйте, git reflog --no-abbrevщоб побачити повне <sha>, яке скорочено за замовчуванням
jkulak

5
Для будь-кого іншого, як я, у кого були проблеми з пошуку ша видаленої гілки: я зміг git checkout remotes/origin/deleted_branch.
Джефф Ірвін

161

Більшу частину часу недосяжні комітети перебувають у релогу. Отже, перше, що потрібно спробувати, - подивитися на рефлог за допомогою команди git reflog(яка відображає рефлог для HEAD).

Можливо, щось простіше, якщо фіксація була частиною певної гілки, яка все ще існує, це використовувати команду git reflog name-of-my-branch. Він також працює з дистанційним пристроєм, наприклад, якщо ви змушені натискати (додаткова порада: завжди віддайте перевагу git push --force-with-leaseзамість того, щоб краще запобігти помилкам і підлягає відшкодуванню).


Якщо ваші зобов’язання не знаходяться у вашому реблоці (можливо, тому, що видалено інструментом сторонніх розробників, який не пише в рефлогу), я успішно відновив гілку, перезавантаживши свою гілку до sha комітету, знайденого за допомогою такої команди (це створює файл з усіма звисаючими комісіями):

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

Для тих, хто перебуває під Windows та подобається графічний інтерфейс, ви можете легко відновити коміти (а також неміцні поетапні файли) за допомогою GitExtensions , скориставшись функцією Repository=> Git maintenance=>Recover lost objects...


Подібна команда для легкого відновлення поетапних файлів видалена: https://stackoverflow.com/a/58853981/717372


2
Величезна допомога. У мене було втрачене зобов’язання, якого ніколи не було в моєму місцевому репо. Перша команда, яка ви там, допомогла мені знайти її на сервері. +1
Шон Адкінсон

1
що псевдонім для порятунку git - це знаток !!! Дуже дякую за внесок!
72A12F4E

2
Ти врятував моє життя.
Джед Лінч

Відповідь Патріка Кооревара мені допомогла, тому що я не знаю останніх видалених розгалужених зобов'язань <sha>.
Монір Хан

@ Монір-хан І? Що я повинен зробити висновок? Відповідь Патріка - це лише копія / вставка моєї команди (з помилкою: він забув фільтрувати на коміти) ...
Філіпп

45

Якщо ви любите використовувати графічний інтерфейс, ви можете виконати всю операцію за допомогою gitk.

gitk --reflog

Це дозволить вам побачити історію філій філії, як ніби гілка не була видалена. Тепер просто клацніть правою кнопкою миші на останньому переході до гілки та виберіть варіант меню Create new branch.


28

Рішення, проголосоване вгорі, насправді більше, ніж вимагається:

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

або

git checkout -b <branch> <sha>

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

Більш чистим (і простішим) рішенням здається однолінійний (після того, як ви знайшли <sha>з git reflog):

git branch <branch> <sha>

Тепер ні ваша нинішня філія, ні невмілі зміни не впливають. Натомість буде створено лише нове відділення аж до <sha>.

Якщо це не вістря, воно все одно спрацює, і ви отримаєте коротшу гілку, тоді ви можете спробувати з новою <sha>і новою назвою гілки, поки не зрозумієте її.

Нарешті, ви можете перейменувати успішно відновлену гілку в те, що вона назвала, або що-небудь інше:

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

Потрібно сказати, що ключовим фактором успіху було знайти правильне виконання зобов'язань <sha>, тому назвіть свої зобов'язання з розумом :)


14

Додавання до т.ут відповідь : є також git-resurrect.sh сценарій в contrib/області джерел Git (в git.git сховища), який може допомогти вам.

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


1
Він працював для мене зараз, хоча мені довелося додати / usr / lib / git-core / до моєї PATH. Але воно не здійснило диво, на яке я сподівався :(
AmanicA

10

Для пошуку та отримання моєї видаленої гілки я використав наступні команди. Перші кроки - з опису 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 (GIT-SHA) на основі коментарів до комірок та скористайтеся ним у наведеній нижче команді. Оформити нову філію під назвою NEW-BRANCH з раніше знайденою GIT-SHA:

$ git checkout -b NEW-BRANCH GIT-SHA

Дуже дякую. Щоб шукати ім’я, знадобилося небагато часу, але час того вартий. Якщо є спосіб також шукати по рядку повідомлення фіксувати, було б набагато краще.
Монір Хан

9

Якщо у вас немає рефлогу, наприклад. оскільки ви працюєте в голому сховищі, у якому не ввімкнено рефлог, і команда, яку ви хочете відновити, створена нещодавно, ще одним варіантом є пошук нещодавно створених об'єктів фіксації та перегляд їх.

Всередині .git/objectsкаталогу запустіть:

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

Тут знаходять усі об’єкти (коміти, файли, теги тощо), створені за останні 12 годин, і фільтрують їх, щоб відображати лише коміти. Перевірка цих ситуацій - це швидкий процес.

Я б спробував спершу скрипт git-ressurect.sh, згаданий у відповіді Якуба .


1
Приємна альтернативна ідея! Однак ваша команда видає помилку. Проблема полягає в частині "12h" (власне "h"). Після того, як я зняв "h", він працював нормально. Від man find: "-ctime n - Статус файлу востаннє змінено n * 24 години тому." Тому ми також повинні змінити 12 на 0,5, щоб очікувана поведінка була протягом останніх 12 годин.
pagliuca

1
Тут я використовую OS X 10.8, тому прапорці «find», наведені вище, базуються на версії, яку він постачає.
Роберт Найт

1
Так, впевнена проблема у версіях! Тому я спочатку підтримав вашу відповідь! Я просто прокоментував, щоб люди зрозуміли, що параметри можуть бути різними.
pagliuca

9

Для користувачів GitHub без встановлення Git:

Якщо ви хочете відновити його з веб-сайту GitHub , ви можете скористатися їх API, щоб отримати список подій, пов’язаних з репо-репортажем:

Спочатку

  • знайдіть ті SHA (виконувати хеші):

    curl -i https://api.github.com/repos/PublicUser/PublicRepo/events

    ... або для приватних репостів:

    curl -su YourUserName https://api.github.com/repos/YourUserName/YourProject/events

    (буде запропоновано пароль GitHub)

    • (Якщо репортаж вимагає двофакторної автентичності, дивіться коментарі до цієї відповіді нижче.)

Далі

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

   • Перейдіть до гілок та видаліть цю.

   •   На цій же сторінці, не завантажуючи , відкрийте DevTools, Панель мережі. Тепер підготуйся ...

   • Клацніть відновити. Ви помітите нову "лінію". Клацніть правою кнопкою миші та виберіть "Скопіювати як курсив" та збережіть цей текст у деякому редакторі.

   • Append до кінця скопійованої рядки коду, це: -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 на бажане ім'я (BTW, чудово зламати перейменування гілки з Інтернету). Якщо ви були не надто повільними, вам потрібно як-небудь зробити цей запит. Наприклад, просто скопіюйте та вставте в термінал.

PS

Я усвідомлюю, що це може бути не "найпростішим рішенням" чи "правильним" рішенням, але воно пропонується у випадку, якщо хтось вважає це корисним.


1
Наведене вище - одне з небагатьох, на яке не покладаються, git reflogі тому було корисним, наприклад, коли видалили віддалену гілку та втратили доступ до комп'ютера, що було зроблено з того, що нічого корисного не можна було отримати reflog. Зверніть увагу , при використанні OAuth або двофакторної аутентифікації на Githubcurl команди стає вид: curl -u username:token https://api.github.com/userабоcurl -H "Authorization: token TOKEN" https://api.github.com/repos/USER_OR_ORG_NAME/REPO_NAME/events
TT--

@ TT-- вау, я радий, що це допомогло! і дякую за ваш внесок щодо авторського маркера :)
Максим Мазурок

8

З мого розуміння, якщо до гілки, яку потрібно видалити, можна отримати іншою гілкою, її можна безпечно видалити, використовуючи

git branch -d [branch]

і ваша робота не втрачена. Пам’ятайте, що гілка - це не знімок, а вказівник на одну. Отже, коли ви видаляєте гілку, ви видаляєте вказівник.

Ви навіть не втратите роботу, якщо видалите гілку, до якої не може дійти інша. Звичайно, це буде не так просто, як перевірити хеш фіксації, але ви все одно можете це зробити. Ось чому Git не в змозі видалити гілку, до якої неможливо дійти -d. Натомість вам доведеться використовувати

git branch -D [branch]

Це частина обов'язкового перегляду відео Скотта Чакона про Git. Перевірте хвилину 58:00, коли він розповідає про гілки та як їх видалити.

Ознайомлення з Git зі Скоттом Чаконом з GitHub


7
Як це допомагає відповісти на запитання?
Дмитро Зайцев

6
Повідомлення запитувача, що гілки не містять вмісту, але насправді є покажчиками. Видаляти гілки вам не потрібно. Ви можете створювати нові, що вказують на те саме, що і видалене .... Ух! Я все ще пам’ятаю, коли я поставив це питання. Гарних часів назад до 2012 року!
fabiopagoti

1
Довелося прокручувати три екрани ДО ПОСЛУГО, щоб знайти відповідь, хто вирішує проблему: видалення гілки - це видалення простого вказівника. Тут немає ситуації з втратою даних, єдине, що потрібно відновити, це те, де це було вказано. Відповіді, які прямують безпосередньо reflog, просто зайві.
RomainValeri

5

Переконайтесь, що виконайте все це локально, і перед тим, як натиснути на Bitbucket Cloud, переконайтеся, що ваше репо знаходиться у бажаному стані. Також може бути хорошою ідеєю клонувати своє поточне репо та спершу протестувати ці рішення.

  1. Якщо ви просто видалили відділення, ви побачите щось подібне у своєму терміналі:
    Deleted branch <your-branch> (was <sha>)

2. Щоб відновити гілку, використовуйте:

    git checkout -b <branch> <sha>

Якщо ви не знаєте "ша" вгорі голови, ви можете:

  1. Знайдіть "sha" для комітету на кінчику видаленої гілки, використовуючи:
    git reflog
  1. Щоб відновити відділення, використовуйте:
    git checkout -b <branch> <sha>

Якщо ваші зобов’язання не містяться у вашому відбитку:

  1. Ви можете спробувати відновити гілку, повторно налаштувавши свою гілку на sha комісії, знайденого за допомогою команди типу:
    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

2. Потім ви можете відображати кожну комісію за допомогою одного з таких:

    git log -p <commit>
    git cat-file -p <commit>

4

Для відновлення видаленої гілки спочатку перегляньте історію релогів,

git reflog -n 60

Де n посилається на останні n комітів. Потім знайдіть відповідну голову і створіть гілку з цією головою.

git branch testbranch HEAD@{30}

4

Я повернув гілку з віддаленого відділу, щоб спробувати очистити кілька комітетів, які я не хотів, і збирався перебрати потрібні, які я хотів. Звичайно, я неправильно написав SHA ...

Ось як я їх знайшов (здебільшого простіший інтерфейс / взаємодія з речей на відповіді тут):

По-перше, створіть список ваших комісій у своєму журналі. Зробіть це якнайшвидше і перестаньте працювати, оскільки вони можуть скидати сміттєзбірник.

git fsck --full --no-reflogs --unreachable --lost-found > lost

Це створює lostфайл із усіма зобов'язаннями, які вам доведеться переглянути. Щоб спростити наше життя, давайте виріжемо з нього лише SHA:

cat lost | cut -d\  -f3 > commits

Тепер у вас є commitsфайл з усіма зобов'язаннями, які ви повинні шукати.

Припустимо, що ви використовуєте Bash, останній крок:

for c in `cat commits`; do  git show $c; read; done

Це покаже вам різницю та здійснить інформацію для кожного з них. І чекаємо, поки ти натиснеш Enter. Тепер запишіть усі, що вам потрібно, а потім виберіть їх у вишні. Після завершення просто натисніть Ctrl-C.


2

ВЕЛИКИЙ ТАК

якщо ви використовуєте GIT, виконайте ці прості кроки https://confluence.atlassian.com/bbkb/how-to-restore-a-deleted-branch-765757540.html

якщо ви використовуєте smartgit і вже підштовхуєте цю гілку до походження, знайдіть цю гілку та клацніть правою кнопкою миші та оформити замовлення


1

Спочатку перейдіть до git batch переходу до вашого проекту, наприклад:

cd android studio project
cd Myproject
then type :
git reflog

У всіх вас є список змін, а номер посилання приймайте номер посилання, а потім оформляйте замовлення
з андроїд-студії або з git betcha. інше рішення: взяти номер ref і перейти в студію Android, клацнути на гілки git вниз, потім натиснути на тег оформлення замовлення або змінити повний контрольний номер, то ось у тебе є гілки.


1

Додавши до відповіді tfe, ви можете відновити цей згаданий процес, якщо тільки це не зібрано сміття. Гілка Git - це просто вказівник на певний фіксатор у дереві комітів. Але якщо ви видалите вказівник, і коміти на цій гілці не об'єднані в іншу існуючу гілку, то git трактує це як звисає доручення та видаляє їх під час збирання сміття, яке може періодично запускатися автоматично.

Якщо вашу гілку не було об'єднано з існуючою гілкою, і якщо вона зібрана сміттям, ви втратите всі комісії до тих пір, доки галузь не буде роздвоєна з існуючої гілки.


1

Пов’язане питання: я прийшов на цю сторінку після пошуку "як знати, що таке видалені гілки".

Видаляючи багато старих гілок, я відчув, що помилково видалив одну з нових гілок, але не знав назви, щоб відновити її.

Щоб знати, які гілки видалено нещодавно, виконайте наступне:

Якщо ви перейдете до своєї Git URL, яка буде виглядати приблизно так:

https://your-website-name/orgs/your-org-name/dashboard

Тоді ви можете побачити канал, що видалено, ким, у недавньому минулому.


Звичайно. Вищеназвана відповідь - для GitHub. Ми встановили GitHub локально. Дякуємо за запитання
Манохар Редді Поредді

1

Я зробив це на комп’ютері, на якому я видалив гілку:

git reflog

відповідь:

74b2383 (develope) HEAD@{1}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: checkout: moving from develope to master
74b2383 (develope) HEAD@{3}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{4}: reset: moving to HEAD
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{5}: clone: from http://LOCALGITSERVER/myBigProject/Android.git

і я отримую гілку за допомогою цієї команди:

git checkout -b newBranchName 74b2383


0

Просто використання git reflogне повернуло shaдля мене. Тільки commit id(який становить 8 символів, а ша - набагато довший)

Так я і використовував git reflog --no-abbrev

А потім зробіть те саме, що було сказано вище: git checkout -b <branch> <sha>


ви завжди можете використовувати скорочений 8 символів, не потрібно використовувати повну ша
Майкл Дрехер

0

ЯКЩО ви використовуєте VSCode ... і ви синхронізували свою гілку з сервером в якийсь момент, перш ніж видалити її ...

Зауважте, що видалення гіти git видаляє лише локальну копію, а не копію на сервері. По-перше, на панелі Git (піктограма git на лівій панелі інструментів) перегляньте гілки та перевірте, чи все ще є ваша гілка під "origin / your_branch_name". Якщо так, просто виберіть це, і вам слід повернути свій код (запропонуйте негайно скопіювати / вставити / зберегти його локально десь в іншому місці).

Якщо ви не бачили "origin / your_branch_name", встановіть розширення GitLens. Це дає змогу візуально проглядатись у сховищах сервера та знаходити копію, яку ви синхронізували із сервером. Якщо у вас є декілька сховищ, зауважте, що для того, щоб сховище з’явилося в GitLens, можливо, буде потрібно хоча б один файл відкрити з потрібного сховища. Тоді:

  1. Відкрийте панель GitLens

  2. Розгорніть сховище

  3. Ви повинні побачити список категорій: Відділення / Співробітники / Віддалені / Сташі / тощо

Ви можете знайти YourLostTreasure у розділі "Відділення" або, можливо, у розділі "Віддалені -> Походження". Сподіваємось, ви побачите гілку з потрібним іменем - якщо розгорнути її, ви побачите файли, які ви змінили у цій гілці. Двічі клацніть назви файлів, щоб відкрити їх, і негайно створіть резервну копію цього коду.

Якщо ви не побачите одразу загублену гілку, поскакуйте, і якщо ви знайдете щось багатообіцяюче, негайно відкрийте її та захопіть код. Мені довелося досить сильно обзиватись, поки я не знайшов TheGoldenBranch, і навіть тоді в коді не було останнього одного або двох збережень (можливо, тому, що я не зміг синхронізуватись із сервером перед спробою a-Branch-Merge, але, випадково натиснувши- Відділення-Видалити). Мій пошук був невиправдано подовжений, тому що, коли я вперше знайшов гілку, я не був повністю впевнений, що ім’я було правильним, тому я постійно шукав, і знадобився певний час, щоб знайти цю першу гілку. (Таким чином, Carpe Carpum і далі продовжуйте шукати.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.