Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [`git cp`](#git-cp)
- [`git create-branch`](#git-create-branch)
- [`git delete-branch`](#git-delete-branch)
- [`git delete-gone-branches`](#git-delete-gone-branches)
- [`git delete-merged-branches`](#git-delete-merged-branches)
- [`git delete-squashed-branches`](#git-delete-squashed-branches)
- [`git delete-submodule`](#git-delete-submodule)
Expand Down Expand Up @@ -932,6 +933,21 @@ Delete local and remote tag `name`:
$ git delete-tag 0.0.1
```

## git delete-gone-branches

Deletes all local branches whose remote-tracking branch has been deleted (i.e. branches shown as `[gone]` in `git branch -vv`). Use `--dry-run` to preview what would be deleted.

```bash
$ git delete-gone-branches
Deleted branch feature-123 (was abc1234).
Deleted branch feature-456 (was def5678).

$ git delete-gone-branches --dry-run
Would delete the following branches:
feature-123
feature-456
```

## git delete-merged-branches

Deletes branches that are listed in `git branch --merged`.
Expand Down
60 changes: 60 additions & 0 deletions bin/git-delete-gone-branches
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bash

set -euo pipefail

dry_run=false
force=false
prune=false

while [[ $# -gt 0 ]]; do
case "$1" in
-n|--dry-run)
dry_run=true
shift
;;
-f|--force)
force=true
shift
;;
-p|--prune)
prune=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: git delete-gone-branches [-n|--dry-run] [-f|--force] [-p|--prune]"
exit 1
;;
esac
done
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to run git fetch --prune before?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a -p/--prune flag that runs git fetch --prune before checking. Kept it opt-in rather than automatic to avoid unexpected network calls.


if [ "$prune" = true ]; then
git fetch --prune
fi

gone_branches=$(git for-each-ref --format \
'%(if:equals=[gone])%(upstream:track,nobracket)%(then)%(refname:short)%(end)' refs/heads/ | sed '/^$/d')
Copy link
Copy Markdown

@mevanlc mevanlc Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with ,nobracket, I think you'll want the if-condition to be:
%(if:equals=gone)
(remove the square brackets)
@codersofthedark


if [ -z "$gone_branches" ]; then
echo "No branches with a gone remote found."
exit 0
fi

if [ "$dry_run" = true ]; then
echo "Would delete the following branches:"
echo "$gone_branches"
exit 0
fi

echo "The following branches will be deleted:"
echo "$gone_branches"

if [ "$force" = false ]; then
read -r -p "Delete these branches? [y/N] " confirm
if [[ ! "$confirm" =~ ^[yY]$ ]]; then
echo "Aborted."
exit 0
fi
fi

echo "$gone_branches" | xargs git branch -D
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we prompt for the branch deletion by default?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an interactive [y/N] confirmation prompt by default. Use -f/--force to skip it (consistent with how git-clear and git-sync handle this in the repo).

6 changes: 6 additions & 0 deletions etc/git-extras-completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ _git-delete-branch() {
__gitex_branch_names_unique
}

_git-delete-gone-branches() {
_arguments \
'(-n --dry-run)'{-n,--dry-run}'[show branches that would be deleted without deleting]'
}

_git-delete-squashed-branches() {
_arguments \
':branch-name:__gitex_branch_names'
Expand Down Expand Up @@ -421,6 +426,7 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
count:'show commit count' \
create-branch:'create branches' \
delete-branch:'delete branches' \
delete-gone-branches:'delete branches whose remote is gone' \
delete-merged-branches:'delete merged branches' \
delete-squashed-branches:'delete squashed branches' \
delete-submodule:'delete submodules' \
Expand Down
54 changes: 54 additions & 0 deletions man/git-delete-gone-branches.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-DELETE\-GONE\-BRANCHES" "1" "March 2026" "" "Git Extras"
.
.SH "NAME"
\fBgit\-delete\-gone\-branches\fR \- Delete branches whose remote is gone
.
.SH "SYNOPSIS"
\fBgit\-delete\-gone\-branches\fR [\-n|\-\-dry\-run] [\-f|\-\-force] [\-p|\-\-prune]
.
.SH "DESCRIPTION"
Deletes all local branches whose remote\-tracking branch has been deleted\. This commonly happens after a pull request is merged and the remote branch is removed\. By default, lists the branches and prompts for confirmation before deleting\.
.
.SH "OPTIONS"
\-n, \-\-dry\-run
.
.P
Show the branches that would be deleted without actually deleting them\.
.
.P
\-f, \-\-force
.
.P
Skip the confirmation prompt and delete branches immediately\.
.
.P
\-p, \-\-prune
.
.P
Run \fBgit fetch \-\-prune\fR before checking for gone branches, to ensure remote\-tracking refs are up to date\.
.
.SH "EXAMPLES"
.
.nf

$ git delete\-gone\-branches

$ git delete\-gone\-branches \-\-dry\-run

$ git delete\-gone\-branches \-\-force

$ git delete\-gone\-branches \-\-prune
.
.fi
.
.SH "AUTHOR"
Written by Utsav Sabharwal <\fIhttps://github\.com/codersofthedark\fR>
.
.SH "REPORTING BUGS"
<\fIhttps://github\.com/tj/git\-extras/issues\fR>
.
.SH "SEE ALSO"
<\fIhttps://github\.com/tj/git\-extras\fR>
135 changes: 135 additions & 0 deletions man/git-delete-gone-branches.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions man/git-delete-gone-branches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
git-delete-gone-branches(1) -- Delete branches whose remote is gone
====================================================================

## SYNOPSIS

`git-delete-gone-branches` [-n|--dry-run] [-f|--force] [-p|--prune]

## DESCRIPTION

Deletes all local branches whose remote-tracking branch has been deleted.
This commonly happens after a pull request is merged and the remote branch
is removed. By default, lists the branches and prompts for confirmation
before deleting.

## OPTIONS

-n, --dry-run

Show the branches that would be deleted without actually deleting them.

-f, --force

Skip the confirmation prompt and delete branches immediately.

-p, --prune

Run `git fetch --prune` before checking for gone branches, to ensure
remote-tracking refs are up to date.

## EXAMPLES

$ git delete-gone-branches

$ git delete-gone-branches --dry-run

$ git delete-gone-branches --force

$ git delete-gone-branches --prune

## AUTHOR

Written by Utsav Sabharwal &lt;<https://github.com/codersofthedark>&gt;

## REPORTING BUGS

&lt;<https://github.com/tj/git-extras/issues>&gt;

## SEE ALSO

&lt;<https://github.com/tj/git-extras>&gt;
1 change: 1 addition & 0 deletions man/git-extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ git-extras(1) -- Awesome GIT utilities
- **git-cp(1)** Copy a file keeping its history
- **git-create-branch(1)** Create branches
- **git-delete-branch(1)** Delete branches
- **git-delete-gone-branches(1)** Delete branches whose remote is gone
- **git-delete-merged-branches(1)** Delete merged branches
- **git-delete-squashed-branches(1)** Delete branches that were squashed
- **git-delete-submodule(1)** Delete submodules
Expand Down
1 change: 1 addition & 0 deletions man/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ git-count(1) git-count
git-cp(1) git-cp
git-create-branch(1) git-create-branch
git-delete-branch(1) git-delete-branch
git-delete-gone-branches(1) git-delete-gone-branches
git-delete-merged-branches(1) git-delete-merged-branches
git-delete-squashed-branches(1) git-delete-squashed-branches
git-delete-submodule(1) git-delete-submodule
Expand Down
Loading