How to remove Git branches that give an error "does not point to a valid object"

85 views Asked by At

I have a Git repository which contains a bunch of remote branches which no longer exist, but when I try to run git fetch -p I get an error:

error: refs/remotes/origin/bad/branch does not point to a valid object!

I can't find any way to fix this. This branch doesn't exist as a separate file in .git/refs/remotes (or anywhere else; I've searched with find). Trying to delete it with git branch -D doesn't work:

$ git branch -D origin/bad/branch
error: branch 'origin/bad/branch' not found.
$ git branch -D bad/branch
error: branch 'bad/branch' not found.

After comments below I tried adding the -r option to the git branch -D and got this error:

$ git branch -D -r origin/bad/branch
error: Couldn't look up commit object for 'refs/remotes/origin/bad/branch'

Is there some magic plumbing command I can use to get rid of this ref, short of just deleting the entire workspace which I would really prefer not to do?

2

There are 2 answers

1
Guildenstern On BEST ANSWER

This command will force-delete a remote-tracking branch:

git branch -D -r origin/bad/branch

But that didn’t work.

When the higher-level commands are too stubborn to do what you want, you might want to try a lower-level command:

git update-ref -d origin/bad/branch

Manually deleting

Note that manually editing things is generally not recommended. But it might be necessary. No warranties.

Refs are to my knowledge currently stored[1] in two possible places:

  • As files under .git/refs
  • As a packed ref in .git/packed-refs (file)

If it’s a file then origin/bad/branch is stored at .git/refs/origin/bad/branch. Just deleting that file should be safe.

If it’s a packed ref: open .git/packes-refs. I have not read any technical documentation for this file format but it just looks like a file on the form:

hash<space>full ref path<newline>

In which case you might find the ref on a line like:

[hash or some nonsense value?]<space>refs/origin/bad/branch<newline>

I guess you could just delete that line. But first do it in a backup of the whole repository (and working tree) just to be safe.

Notes

  1. There is currently (2024-03-01) ongoing work on a “reftable backend”. I don’t know what that concretely is but you should expect a binary format which is not as easy to manually muck with.
7
Adam Hess On

git is not magic. It needs to store its information somewhere and that somewhere is the .git directory. it stores all the configuration, objects and references pertaining to your current project/repository.

.git/refs contains all the references you have in your repository.

The .git/refs/HEADS list all the references that you're managing locally. If you open any of those files you'll see there is a hash there, this references to the commit that that branch references. You likely look in there and simply delete the reference to the branch that you're referring too. (keep in mind if that branch doesn't exist in the origin, i.e., your server, you've effectively lost your work unless you can remember your branch name and GC hasnt cleaned up the dangling references.)

its also not hard to figure out that .git/refs/remotes/ refers to all servers that you've connected your git repo to and there references stored there. In most cases you'll just have an origin directory.

If you want to see it in action, rename the .git/refs/remotes/origin directory and run git pull you'll see the logs show that there are new branches to refer to.

Basically delete the offending branch that's in your local .git/refs/HEADS folder that corresponds to the branch giving you a hard time and try again.