RFC: How should we handle un-deleted remote branches?
- From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- Date
- Apr 20, 2018, 12:14 UTC
- Message-ID
- <87in8mdqhr.fsf@evledraar.gmail.com>
I removed a remote and its refs persisted. At first I thought this was a bug but looking at add_branch_for_removal()'s "don't delete a branch if another remote also uses it" logic it's intentional.
This goes very wrong if you do e.g.:
(
rm -rf /tmp/git &&
git clone --bare --mirror git@github.com:git/git.git /tmp/git &&
cd /tmp/git &&
git remote add avar git@github.com:avar/git.git &&
git fetch avar &&
git remote remove avar &&
git for-each-ref|grep -c refs/remotes/avar
)At this point you can't prune it since no remote config is left:
$ git remote prune avar
fatal: 'avar' does not appear to be a git repository
fatal: Could not read from remote repository.But this is a possible work-around:
git init /tmp/empty.git
git remote add avar file:///tmp/empty.git
git remote prune avar
git remote remove avarOr use update-ref -d to remove them:
for rr in $(git for-each-ref --format="%(refname)"|grep ^refs/remotes/avar/)
do
git update-ref -d $rr
doneI started to patch this, but I'm not sure what to do here. we could do some combination of:
0. Just document the current behavior and leave it.
1. Dig further down to see what other remotes reference these refs, and
just ignore any refspecs that don't explicitly reference
refs/remotes/<our_deleted_remote>/*. I.e. isn't the intention here to preserve a case where you have two
URLs for the same effective remote, not whene you have something
like a --mirror refspec? Unfortunately I can't ask the original
author :( 2. Warn about each ref we didn't delete, or at least warn saying
there's undeleted refs under refs/remotes/<name>/*. 3. Make 'git remote remove --force-deletion <name>' (or whatever the
flag is called) be a thing. But unless we do the next item this
won't be useful. 4. Make 'git remote prune <name>' work in cases where we don't have a
remote called <name> anymore, just falling back to deleting
refs/remotes/<name>. In this case 'git remote remove
--force-deletion <name>' would also do the same thing.In any case, the current behavior where we just leave this crap behind without any explanation or an obvious way to delete them (can't use git-branch -d, need update-ref -d) isn't nice.
I encountered this in the wild because GitLab will add an "upstream" ref if you clone a repo, but if you stop using the remote to update it in combination with their "geo" remote (which has --mirror refspecs) it'll leave behind all these dead refs.