git error: There are still logs under
Apparently there used to be a tpickel/RS/foo
(for some name foo
).
Your Git recorded information about that, in .git/logs/refs/remotes/tpickel/RS/foo
. Now your Git is trying to create a file named .git/logs/refs/remotes/tpickel/RS
, which will record information about the new branch tpickel/RS
. It cannot do so because there is a directory, .git/logs/refs/remotes/tpickel/RS
, in the way. The in-the-way directory contains some file (foo
, or some other name, there's nothing above to show what the actual name is), which is how your Git was keeping a reflog for tpickel/RS/foo
.
Now that remote branch tpickel/RS
is gone, your Git needs to remove both refs/remotes/tpickel/RS/foo
and its reflog file. Ideally, git fetch --prune tpickel
will do both of those all at once for you, before trying to also create tpickel/RS
and its reflog, which is what is failing because of the lingering tpickel/RS/foo
.
If the --prune
works, you're done. If not, you will have to go in to .git/logs/refs/remotes/tpickel/
and either remove all of the RS
and RS/*
entries, or rename them to get them out of the way. (If you want to save these, despite the remote tpickel
having dropped the branch, move them rather than deleting them, and don't let git fetch --prune
delete them. You probably do not want to save them though.)
What --prune
means
When you run git fetch remote
(such as git fetch tpickel
), Git contacts the named remote
and gets from it a list of all its references. You can view this list yourself at any time by running git ls-remote remote
: this invokes the same start but then stops after getting the list, rather than continuing on to do the fetch.
Suppose that (as is the normal default case) your Git is instructed to copy all their branch references to remote-tracking branches. In this particular example, that would mean copying refs/heads/master
to refs/remotes/tpickel/master
, for instance. This kind of copying is generally additive: if remote tpickel
has branches master
and develop
today, and tomorrow they add feature
, you will have two remote-tracking branches today and you will add a new one tomorrow when you fetch their feature
. At some point, though, they may remove a branch. What if they remove feature
when you are still using refs/remotes/tpickel/feature
?
Git's answer to this puzzle is to default to keeping any copied reference forever. As you have just seen, this can sometimes gets in the way of new branches after old branches have been removed, so this solution is not at all perfect. What adding --prune
does is to take the complete list, compare it to your set of remote-tracking branches, and delete from your local repository any remote-tracking branch that has no corresponding branch on the remote. That is, just because we had copied their refs/heads/develop
to our refs/remotes/tpickel/develop
yesterday, does not mean we should keep refs/remotes/tpickel/develop
today, if their refs/heads/develop
is gone. So if you specify --prune
, Git looks for such occurrences and deletes any stale remote-tracking branches.
This code has been around for a while (since 1.7 or so I think). Git version 1.8.5 added two configuration items: fetch.prune
and remote.remote.prune
(e.g., remote.tpickel.prune
). If fetch.prune
is set to true
, git fetch
always prunes; if the specific remote's configuration is set to true
, git fetch
prunes that specific remote.
(The code was improved a bit in version 2.0.0 of Git to handle potential ambiguous mappings. This covers cases where multiple upstream references can potentially map to the same remote-tracking reference. With normal setups, this never happens: it can only occur if you make up your own fetch
entries for some named remote.)
Running "rm -rf .git/logs" solved my problem.