Git:恢复已删除(远程)分支


94

我需要恢复在推送期间以某种方式删除的两个Git分支。

这两个分支是在不同的系统上创建的,然后被推送到我的“共享”(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“撤消”信息都与恢复丢失的提交有关。我不认为这适用于此,因为我没有这些分支的提交UID。

我想知道如何找回这些。我还想知道如何首先删除它们,以及将来如何避免这种情况。

编辑:根据要求,这是我的回购配置

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 2010年

很有可能;我已经贴了
Craig Walker 2010年

2
您的remote.origin.fetchrefspec不适合与一起使用remote.origin.mirror = true。您想镜像还是要将GitHub存储库用作普通遥控器?我的答案应该包含您需要的两种命令。
克里斯·约翰森

我猜想在第二个存储库中,不再可以选择镜像(这可能首先导致了删除)。
Craig Walker 2010年

Answers:


102

我不是专家。但是你可以尝试

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

查找已删除分支的HEAD提交并将其取回。


我之前尝试过fsck;您知道如何找出正确的提交吗?我有20个可以尝试。
Craig Walker 2010年

1
做到了;一旦我收到提交消息,就将git branch <uid>它们取回。谢谢!
Craig Walker 2010年

很高兴听到。确保还解决了您remotes.origin.mirrorremotes.origin.fetch设置之间的冲突,否则,您势必会再次遇到问题(或无意中从其他存储库推送了内容提交)。
克里斯·约翰森

@Craig:很乐意提供帮助:)
iamamac

3
我今天失去了候选发布分支。不知道提交ID。使用以下方法将其恢复:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
spezifanta

23

仅有两个命令可以挽救我的生命

1.这将列出所有先前的HEAD

git reflog

2.这将还原HEAD以提交您删除的内容。

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

1
我从未在本地签入分支,因此我的HEAD从未在那儿签到过,因此无法使用来找到提交ID git reflog。还有什么我可以尝试的吗?
zyy

1
与@zyy相同提交已被远程的其他团队成员删除,因此我必须将其恢复到本地计算机(我从未在本地进行该提交)并将其推回...
OmGanesh

11

您删除的分支不会丢失,它们通过您显示的获取操作被复制到origin / contact_pageorigin / new_pictures的 “远程跟踪分支”中(它们也通过您显示的推送而被撤回,但它们被推送到了refs / remotes / origin /而不是refs / heads /)。检查git log origin/contact_pagegit log origin/new_pictures查看您的本地副本是否“最新”,以及您认为应该存在的内容。如果在您显示的获取和推送之间有任何新的提交(从其他回购)推送到那些分支上,则可能“丢失”了这些(但您可能会在最近推送这些分支的另一个回购中找到它们) 。

提取/推送冲突

看来您是以正常的“远程模式”获取(远程ref / heads /本地存储在refs / remotes / origin /中),但以“镜像模式”推送(本地ref /被推送到远程ref /) 。检查您的.git / config并协调remote.origin.fetchremote.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

您最终可能还希望删除所有的ref / remotes / origin / refs,因为如果在镜像模式下运行,它们将无用(您的普通分支代替了通常的远程跟踪分支)。

选项B:重新配置为普通遥控器

但是,由于您似乎正在将此远程存储库与多个“工作”存储库一起使用,因此您可能不想使用镜像模式。您可以尝试以下方法:

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

然后,您最终将要删除远程仓库中的伪造的ref / remotes / origin refs 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':未知版本或不在工作树中的路径”:-\谢谢。
Craig Walker 2010年

1
好吧,那些分支在那里,您的推送日志显示了它。当寻找裁判.git目录,一定要检查.git/packed_refs.git/refs/git show-ref将丢弃所有本地裁判(打包或“松散”)。您仍然应该能够在原先将其推送到GitHub仓库(在另一台机器上?别人的仓库?)上的仓库中找到引用。如果做不到这一点,只要你有没有做过GC或修剪,你应该能够在git fsck输出检查晃来晃去提交并重新安装它们:git branch contact_page-recovered <SHA-1-of-dangling-commit>
克里斯·约翰森

packing_refs也没有。这些提交肯定是悬而未决的。不知道那是怎么回事。谢谢您的帮助!
Craig Walker 2010年

8

如果删除是最近的(例如,哦,不!!),您仍然应该收到一条消息:

Deleted branch <branch name> (was abcdefghi).

您仍然可以运行:

git checkout abcdefghi

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


8
  1. 找出coimmit id

    git reflog

  2. 恢复错误删除的本地分支

    git branch need-recover-branch-name commitId

  3. 如果您之前也删除了远程分支,请再次推送Need-recover-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
Craig Walker 2010年

好的,我想我知道发生了什么事(尽管完整的错误会有所帮助)。push已更新了已删除的分支,并在本地删除了该引用,这也是一个跟踪引用。怎么git rev-parse refs/remotes/origin/origin/contact_page说呢?由于伪造的“ mirror”配置,因此现在可以在本地存储库中引用该分支。
CB Bailey 2010年

嗨,查尔斯;自从我写了这篇文章以来,我一直在修改(并修复)我的配置,所以我再也无法获得(有意义的)rev-parse输出了。但是,我认为遥控器中没有双重嵌套的“原始”目录。
Craig Walker 2010年

0

如果您的组织使用JIRA或绑定到git的其他类似系统,则可以找到票证本身列出的提交,然后单击代码更改的链接。Github删除了分支,但仍然具有可用于挑选樱桃的提交。


-1

看起来似乎太谨慎了,但是在更改源代码控制之前,我经常压缩一份我一直在做的事情的副本。在我正在处理的Gitlab项目中,我最近误删除了一个合并分支请求后想要保留的远程分支。事实证明,我再次要做的就是将提交历史恢复到原来的状态。合并请求仍由Gitlab跟踪,因此它仍在分支的右侧显示蓝色的“合并”标签。我仍然压缩本地文件夹,以防万一发生不良情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.