Git: Recover deleted (remote) branch
I need to recover two Git branches that I somehow deleted during a push.
These two branches were created on a different system and then pushed to my "sha开发者_开发问答red" (github) repository.
On my system, I (apparently) retrieved the branches during a fetch:
~/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
Right after that I did a push to send my local changes up to the central repo. For some reason, these branches were deleted from both my local system and the central repo:
~/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
It's not terribly easy to get the branches off of their birthplace machine, so I'd like to try and recover them from my local if possible.
All of the git "undo" information I've googled has to with recovering lost commits. I don't think that applies here, since I don't have commit UIDs for these branches.
I'd like to know how I can get these back. I'd also like to know how they were deleted in the first place and how I can avoid this in the future.
EDIT: by request, here's my repo configuration
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
I'm not an expert. But you can try
git fsck --full --no-reflogs | grep commit
to find the HEAD commit of deleted branch and get them back.
just two commands save my life
1. This will list down all previous HEADs
git reflog
2. This will revert the HEAD to commit that you deleted.
git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02
find out commit id
git reflog
recover local branch you deleted by mistake
git branch <NEED-RECOVER-BRANCH-NAME> commitId
push need-recover-branch-name again if you deleted remote branch too before
git push origin <NEED-RECOVER-BRANCH-NAME>
Your deleted branches are not lost, they were copied into origin/contact_page and origin/new_pictures “remote tracking branches” by the fetch you showed (they were also pushed back out by the push you showed, but they were pushed into refs/remotes/origin/ instead of refs/heads/). Check git log origin/contact_page
and git log origin/new_pictures
to see if your local copies are “up to date” with whatever you think should be there. If any new commits were pushed onto those branches (from some other repo) between the fetch and push that you showed, you may have “lost” those (but probably you could probably find them in the other repo that most recently pushed those branches).
Fetch/Push Conflict
It looks like you are fetching in a normal, ‘remote mode’ (remote refs/heads/ are stored locally in refs/remotes/origin/), but pushing in ‘mirror mode’ (local refs/ are pushed onto remote refs/). Check your .git/config and reconcile the remote.origin.fetch
and remote.origin.push
settings.
Make a Backup
Before trying any changes, make a simple tar or zip archive or your whole local repo. That way, if you do not like what happens, you can try again from a restored repo.
Option A: Reconfigure as a Mirror
If you intend to use your remote repo as a mirror of your local one, do this:
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
You might also eventually want to do delete all your refs/remotes/origin/ refs, since they are not useful if you are operating in mirror mode (your normal branches take the place of the usual remote tracking branches).
Option B: Reconfigure as a Normal Remote
But since it seems that you are using this remote repo with multiple “work” repos, you probably do not want to use mirror mode. You might try this:
git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror
Then, you will eventually want to delete the bogus refs/remotes/origin refs in your remote repo: git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures …
.
Test Push
Try git push --dry-run
to see what it git push
would do without having it make any changes on the remote repo. If you do not like what it says it is going to do, recover from your backup (tar/zip) and try the other option.
If the delete is recent enough (Like an Oh-NO! moment) you should still have a message:
Deleted branch <branch name> (was abcdefghi).
you can still run:
git checkout abcdefghi
git checkout -b <some new branch name or the old one>
The data still exists out in github, you can create a new branch from the old data:
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
If your organization uses JIRA or another similar system that is tied into git, you can find the commits listed on the ticket itself and click the links to the code changes. Github deletes the branch but still has the commits available for cherry-picking.
I think that you have a mismatched config for 'fetch' and 'push' so this has caused default fetch/push to not round trip properly. Fortunately you have fetched the branches that you subsequently deleted so you should be able to recreate them with an explicit push.
git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures
It may seem as being too cautious, but I frequently zip a copy of whatever I've been working on before I make source control changes. In a Gitlab project I'm working on, I recently deleted a remote branch by mistake that I wanted to keep after merging a merge request. It turns out all I had to do to get it back with the commit history was push again. The merge request was still tracked by Gitlab, so it still shows the blue 'merged' label to the right of the branch. I still zipped my local folder in case something bad happened.
精彩评论