Search code examples
gitgit-branchgit-update-ref

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


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?


Solution

  • 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.