Subject: Re: [PATCH] fetch: add fetch.pruneLocalBranches config

From: Junio C Hamano <[email-masked]>
Date: Mon, 04 May 2026 07:39:47 +0900

"Harald Nordgren via GitGitGadget" <[email-masked]> writes:

> Introduce a tri-state config option that, when --prune (or
> fetch.prune / remote.<name>.prune) removes a remote-tracking
> ref, also deletes local branches whose configured upstream is
> that ref.
>
> Values:
> - false (default): no change in behavior.
> - safe: delete only if the local tip is reachable from the
>   upstream tip, preserving any unpushed work.
> - force: delete unconditionally; recoverable only via reflog.
>
> The currently checked-out branch is always preserved.

I do like the feature that allows you to identify which local
branches are already merged and prune them.  It will help users keep
their local branch namespace clean.

I however do not like to see the feature tied to "fetch".  By this,
I do not mean I do not want an option to trigger the feature when
"git fetch" is run.  What I mean is that users should have an option
to prune merged branches without having to fetch first.  And you can
then optionally trigger that machinery from "git fetch".

Of course they aleady can do something silly like

    $ git branch -d $(git branch --list | sed -e 's/^..//')

and remove all the merged branches, but compared to what is
presented here, one thing missing is that you allow pruning the
local branches that are merged only to remote-tracking branches from
a single remote.

To break the feature down to make it easier to use by our users with
various needs and workflows, we would benefit from having a
collection of smaller features that can be composed, like these:

 * "git branch --forked <remote>" lists local branches that build on
   something taken from <remote>s.  The option can be given multiple
   times to make a union of the results from individual "--forked
   <remote>".

   - <remote> may be a name of a remote, e.g., "origin" to mean all
     the remote-tracking branches "refs/remotes/origin/*", 

   - <remote> may be "origin/master" to name a specific
     remote-tracking branch.

   - There may be other handy things to cover with <remote>, like
     "--all" that may act as if you listed all the available
     <remote> on the command line.

 * "git branch --prune-merged <remote>..." is a short-hand for "git
   branch -d $(git branch --forked <remote>...".

 * "git fetch/pull --prune-merged <remote>" can trigger "git branch
   --prune-merged <remote>" after "git fetch" successfully updates
   the remote-tracking branches, which should be equivalent to what
   you have here..

Some local branches that fork from remote and have their initial
round already merged may not want to be pruned, however.  You may
have multi-stage development plans for that topic, and you know
already the second phase would want to build on top of the initial
round, not a random version of the mainline with many topics from
other folks merged in.  So you'd rather want to keep the topic
branch around after your initial round has been merged to the
upstream before you start the second phase.  This is especially true
if your topic is designed to apply to an existing release (in other
words, a bugfix) and you want to keep the second and subsequent
rounds of the topic to be applicable to the same target version
without contaminating the topic with irrelevant features from others
that happened to have been developed and merged upstream around the
same time.

And we'd need to cater to their needs.  By this, I do not mean "they
do not have to use --prune-merged", but by giving them a way to say
"this branch should not be auto-pruned with --prune-merged".