Reputation: 9594
In a Git repo how can I efficiently remove local tracking branches for deleted remote branches?
If I create a Github repo, then create a feature branch off master, then the Git cli shows this
user@workstation C:\Home\Development\Workspaces\Scratch\GitTest1
$ git branch -vv
* feature1 e1f5c4e [origin/feature1] Stuff added on branch feature1
master d7a1ee8 [origin/master] Initial commit
user@workstation C:\Home\Development\Workspaces\Scratch\GitTest1
$ git branch -a
* feature1
master
remotes/origin/feature1
remotes/origin/master
I can see what remote branches my local branches are tracking and everything is good.
If I delete the feature branch from Github and fetch --prune
.
user@workstation C:\Home\Development\Workspaces\Scratch\GitTest1
$ git fetch --prune
From https://github.com/Neutrino-Sunset/git-test
- [deleted] (none) -> origin/feature1
But now git branch -vv
still shows the deleted remote branch, even though git branch -a
no longer lists it.
user@workstation C:\Home\Development\Workspaces\Scratch\GitTest1
$ git branch -vv
* feature1 e1f5c4e [origin/feature1: gone] Stuff added on branch feature1
master d7a1ee8 [origin/master] Initial commit
user@workstation C:\Home\Development\Workspaces\Scratch\GitTest1
$ git branch -a
* feature1
master
remotes/origin/master
Because of this the only way I have to keep my local repository synchronised with my remote is to run git branch -vv
in one console, git branch -a
in another console. Then manually compare which of my local branches that say they are tracking a remote branch are actually tracking a branch that doesn't even exist, and then in a third console manually delete the extraneous branches.
For a large repo it's astonishingly cumbersome, and very easy to make a mistake.
Does Git really not provide a more intelligent way to do this?
Upvotes: 2
Views: 253
Reputation: 28934
I agree with torek's comment and would like to elaborate on the why.
Conceptually, let's start with a more generalized question:
In a Git repo how can I efficiently remove local branches that I no longer need?
Because everyone's workflow might be different, there isn't a good catch-all for determining which you branches you no longer need. The standard answer that Git supports is:
main
, master
, or develop
), then you no longer need it. This is because there is no information on that branch that isn't already stored elsewhere (except for the branch name). You can re-create the branch in the future if you decide you need it again.When I say that Git supports deleting branches that are fully merged, by this I mean when you delete a branch you can specify -d
to perform the delete if the branch is fully merged (into either your currently checked out branch or another specified branch), or you can use -D
to delete the branch regardless.
There are other reasons you may no longer need a branch, that don't meet the criteria in #1, some of which may be:
-D
instead of -d
when they delete their branch.)Now to your specific question (paraphrased):
In a Git repo how can I efficiently remove local branches for deleted remote branches?
One obvious way would be to use the method you suggested, but with the word "gone" next to it. This should catch most of the branches you can delete in #1 and #4, but it's still not perfect. It doesn't catch the case where you added a commit to your local branch and forgot to push it out before the PR was completed! If you aren't worried about that possibility, then your approach should work, and can probably be automated. (See VonC's answer for some ideas.)
If you don't want to risk deleting extra commits on your branches that were never pushed, then the one thing Git supports is the one thing that you know with certainty is safe, which is deleting fully merged branches. So given that, you could safely iterate through every one of your local branches, use the -d
argument against a permanent branch such as develop
or main
, and sleep well at night. The issue with that is that you'll probably still have many more branches leftover that you can delete.
If you have a rebase on-the-fly workflow, then you can also use this algorithm:
main
)X
,T
from X
.T
onto main
T
and main
. If they are identical, you can delete branch X
.Now for the remainder of your branches, you'll just have to look at them manually. I suggest listing your local branches a few times per day and keeping them purged all the time, since you'll know which PRs have recently been completed. If you wait too long it gets messy. (Sort of like an Email Inbox, or perhaps more analogous is the Email Drafts Folder. I think I have over 50 drafts in mine, and there might be 1 or 2 I don't want to delete for some reason, and therefore they all will stay until I dedicate time to purging them.)
Upvotes: 1