Git: восстановить удаленную (удаленную) ветку


95

Мне нужно восстановить две ветки Git, которые я каким-то образом удалил во время push.

Эти две ветки были созданы в другой системе и затем помещены в мой «общий» (github) репозиторий.

В моей системе я (по-видимому) получил ветки во время выборки:

~/myfolder> git fetch
remote: Counting objects: 105, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 62 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (62/62), done.
From github.com:mygiturl
 * [new branch]      contact_page -> origin/contact_page
   731d1bb..e8b68cc  homepage   -> origin/homepage
 * [new branch]      new_pictures -> origin/new_pictures

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

~/myfolder> git push
Counting objects: 71, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (49/49), 4.99 KiB, done.
Total 49 (delta 33), reused 0 (delta 0)
To git@github.com:mygiturl.git
 - [deleted]         contact_page
 + e8b68cc...731d1bb homepage -> homepage (forced update)
   bb7e9f2..e0d061c  master -> master
 - [deleted]         new_pictures
   e38ac2e..bb7e9f2  origin/HEAD -> origin/HEAD
   731d1bb..e8b68cc  origin/homepage -> origin/homepage
   e38ac2e..bb7e9f2  origin/master -> origin/master
 * [new branch]      origin/contact_page -> origin/contact_page
 * [new branch]      origin/new_pictures -> origin/new_pictures

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

Вся информация о git "undo", которую я нашел в Google, связана с восстановлением потерянных коммитов. Я не думаю, что здесь это применимо, поскольку у меня нет идентификаторов фиксации для этих веток.

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

РЕДАКТИРОВАТЬ: по запросу, вот моя конфигурация репо

user.name=Craig Walker
user.email=github@softcraft.ca
alias.unadd=reset HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=git@github.com:MyGitURL.git
remote.origin.mirror=true
branch.master.remote=origin
branch.master.merge=refs/heads/master
alias.undo=reset --hard
alias.test=push -f ci HEAD:master
alias.st=status
alias.ci=commit
alias.br=branch
alias.co=checkout
alias.ch=checkout
alias.df=diff
alias.lg=log -p
alias.who=shortlog -s --
remote.ci.url=ContinuousIntegrationGitURL
remote.ci.fetch=+refs/heads/*:refs/remotes/ci/*
branch.photo.remote=origin
branch.photo.merge=refs/heads/photos
remote.foo.url=FooGitURL
remote.foo.fetch=+refs/heads/*:refs/remotes/cynthia/*
branch.homepage.remote=origin
branch.homepage.merge=refs/heads/homepage

Похоже, у вас «необычная» или несоответствующая конфигурация извлечения и отправки. Что git config -lпоказывает локальный репозиторий?
— CB Bailey

Вполне возможно; Я выложил это.
— Крейг Уокер

2
Ваш remote.origin.fetchrefspec не подходит для использования с remote.origin.mirror = true. Вы хотите отразить или использовать репозиторий GitHub как обычный пульт? В моем ответе должны быть команды, которые вам нужны в любом случае.
— Крис Джонсен

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

Ответы:


103

Я не специалист. Но ты можешь попробовать

git fsck --full --no-reflogs | grep commit

чтобы найти фиксацию HEAD удаленной ветки и вернуть их.


Я пробовал fsck раньше; ты знаешь, как узнать, какой коммит правильный? У меня есть 20 попыток.
— Craig Walker

1
Это сделало это; как только я получил сообщения фиксации, я git branch <uid>получил их обратно. Благодарность!
— Крейг Уокер,

Приятно слышать. Не забудьте также разрешить конфликт между вашим remotes.origin.mirrorи remotes.origin.fetchнастройками, в противном случае вы обязаны снова столкнуться с проблемой (или неумышленно CLOBBER фиксаций толкнули от других сделок РЕПО).
— Крис Джонсен

@Craig: Рад быть полезным :)
— iamamac

3
Сегодня я потерял ветку релиз-кандидата. Не знал идентификатор фиксации. Получил восстановление с помощью:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
— spezifanta 05

23

всего две команды спасают мою жизнь

1. Это список всех предыдущих заголовков

git reflog

2. Это вернет HEAD для фиксации, которую вы удалили.

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02

1
Я никогда не заходил в ветку локально, поэтому моего HEAD там никогда не было, поэтому я не могу найти идентификатор фиксации с git reflog. Что еще я могу попробовать?
— зыы

1
То же, что и @zyy Коммит был удален другим членом команды удаленно, поэтому мне нужно вернуть его на свой локальный компьютер (у меня никогда не было этого коммита локально) и вернуть его обратно ...
— ОмГанеш,

11

Ваши удаленные ветки не потеряны, они были скопированы в origin / contact_page и origin / new_pictures «ветки удаленного отслеживания» с помощью полученной вами выборки (они также были вытеснены назад показанным вами push, но они были помещены в refs / remotes / origin / вместо refs / heads /). Проверьте git log origin/contact_pageи , git log origin/new_picturesчтобы увидеть , если ваши локальные копии «до даты» с тем, что вы думаете , должны быть там. Если какие-либо новые коммиты были помещены в эти ветки (из какого-то другого репо) между извлечением и отправкой, которые вы показали, вы могли их «потерять» (но, вероятно, вы могли бы найти их в другом репо, которое совсем недавно подтолкнуло эти ветки) .

Конфликт загрузки / извлечения

Похоже, вы выполняете выборку в обычном, «удаленном режиме» (удаленные ссылки / головы / хранятся локально в refs / remotes / origin /), но нажимаете в «зеркальном режиме» (локальные ссылки / помещаются в удаленные ссылки /) . Проверьте .git / конфигурацию и примирить remote.origin.fetchи remote.origin.pushнастройку.

Сделать резервную копию

Прежде чем пытаться внести какие-либо изменения, создайте простой tar или zip-архив или все локальное репо. Таким образом, если вам не нравится то, что происходит, вы можете попробовать еще раз из восстановленного репо.

Вариант A: перенастроить как зеркало

Если вы намерены использовать удаленное репо как зеркало локального, сделайте следующее:

git branch contact_page origin/contact_page &&
git branch new_pictures origin/new_pictures &&
git config remote.origin.fetch '+refs/*:refs/*' &&
git config --unset remote.origin.push &&
git config remote.origin.mirror true

Вы также можете в конечном итоге удалить все ваши refs / remotes / origin / refs, поскольку они бесполезны, если вы работаете в зеркальном режиме (ваши обычные ветки заменяют обычные ветки удаленного отслеживания).

Вариант B: перенастроить как обычный пульт

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

git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror

Затем, вы в конечном итоге хотите удалить фиктивные ссылки / пультов ДУ / происхождения рефов в удаленном репо: git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures ….

Тестовый толчок

Попробуйте git push --dry-runпосмотреть, что он git pushбудет делать, не внося никаких изменений в удаленное репо. Если вам не нравится то, что он собирается делать, восстановитесь из резервной копии (tar / zip) и попробуйте другой вариант.


1
Я не думаю, что ветки удаленного отслеживания сохранились, если они вообще были скопированы. 'git branch -a' их не показывает, и я также не могу найти файлы с такими именами в каталоге .git. Наконец, рекомендуемые вами команды «git log» возвращают «фатальный: неоднозначный аргумент 'origin / contact_page': неизвестная ревизия или путь не в рабочем дереве»: - \ Тем не менее, спасибо.
— Крейг Уокер

1
Ну, эти ветки были там, ваш журнал push показывает это. При поиске ссылок в .gitкаталоге обязательно проверьте .git/packed_refsв дополнение к .git/refs/. git show-refвыгружает всех ваших местных референсов (упакованных или «незакрепленных»). Вы по-прежнему сможете найти ссылки в репозитории, которые изначально отправили их в репозиторий GitHub (на другом компьютере? В чужом репо?). В противном случае, до тех пор , пока вы не сделали дс или чернослив, вы должны быть в состоянии к git fsckвыходу , чтобы исследовать свисающие фиксаций и их прикрепить: git branch contact_page-recovered <SHA-1-of-dangling-commit>.
— Крис Джонсен

Pack_refs тоже не было. Коммиты определенно болтались; не знаю, как это случилось. Спасибо за вашу помощь!
— Крейг Уокер,

8

Если удаление произошло достаточно недавно (например, в момент О-НЕТ!), Вы все равно должны получить сообщение:

Deleted branch <branch name> (was abcdefghi).

вы все еще можете бегать:

git checkout abcdefghi

git checkout -b <some new branch name or the old one>


8
  1. узнать идентификатор Коиммита

    git reflog

  2. восстановить локальную ветку, которую вы удалили по ошибке

    git branch need-recover-branch-name commitId

  3. снова нажмите need-recovery-branch-name, если вы тоже удалили удаленную ветку

    git push origin need-recover-branch-name


2
Это сработало для меня. Я предпочитаю принятый ответ, потому что это было намного меньше шагов. Я смог увидеть свое сообщение о фиксации git reflog, вместо того, чтобы угадывать и git show.
— theUtherSide

3

Данные все еще существуют в github, вы можете создать новую ветку из старых данных:

git checkout origin/BranchName #get a readonly pointer to the old branch
git checkout –b BranchName #create a new branch from the old
git push origin BranchName #publish the new branch

1

Я думаю, что у вас несоответствующая конфигурация для «выборки» и «толчка», поэтому это привело к тому, что выборка / отправка по умолчанию не выполнялась должным образом. К счастью, вы получили ветки, которые впоследствии удалили, так что вы сможете воссоздать их с помощью явного нажатия.

git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures

Как и в случае с моим комментарием к @Chris Johnson, похоже, что ветки больше (никогда?) Не существуют локально. Когда я git push origin origin/contact_page:contact_pageполучаю это: error: src refspec origin/contact_page does not match any
— Крейг Уокер

Хорошо, я думаю, что понимаю, что произошло (хотя полная ошибка была бы полезна). push обновил удаленную ветку и удалил ссылку локально, а также ссылку для отслеживания. Что git rev-parse refs/remotes/origin/origin/contact_pageговорит? Из-за фальшивой конфигурации «зеркало» ветка my теперь упоминается здесь, в локальном репозитории.
— CB Bailey

Привет, Чарльз; Поскольку я написал это, я изменил (и исправил) свою конфигурацию, поэтому я больше не могу получить (значительный) вывод rev-parse. Однако я не думаю, что в пультах был двойной вложенный каталог "origin".
— Крейг Уокер

0

Если ваша организация использует JIRA или другую подобную систему, связанную с git, вы можете найти коммиты, перечисленные в самом билете, и щелкнуть ссылки на изменения кода. Github удаляет ветку, но коммиты по-прежнему доступны для выбора.


-1

Это может показаться слишком осторожным, но я часто заархивирую копию всего, над чем я работал, прежде чем вносить изменения в систему контроля версий. В проекте Gitlab, над которым я работаю, я недавно по ошибке удалил удаленную ветку, которую хотел сохранить после слияния запроса на слияние. Оказывается, все, что мне нужно было сделать, чтобы вернуть его с историей коммитов, - это снова нажать. Запрос на слияние все еще отслеживался Gitlab, поэтому справа от ветки по-прежнему отображается синяя метка «объединено». Я все еще заархивировал свою локальную папку на случай, если что-то случится.

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