git-trim
automatically trims your tracking branches whose upstream branches are merged or stray.
git-trim
is a missing companion to the git fetch --prune
and a proper, safer, faster alternative to your <bash oneliner HERE>
Instruction | Configurations | FAQ
Download binary from Releases, and put it under your PATH
directories.
You can also install with cargo install git-trim
if you have cargo
.
It uses git2
under the hood which depends conditionally on openssl-sys
on *nix platform.
You might need to install libssl-dev
and pkg-config
packages if you build from the source. See: https://docs.rs/openssl/0.10.28/openssl/#automatic
- Don't forget to set an upstream for a branch that you want to trim automatically.
git push -u <remote> <branch>
will set an upstream for you on push. - Run
git trim
if you need to trim branches especially after PR reviews. It'll automatically recognize merged or stray branches, and delete it. - You can also
git trim --dry-run
when you don't trust me.
Don't forget to git config trim.bases develop,master
.
There are so many lines of commands to type and many statuses of branches that corresponding to PRs that you've sent. Were they merged or rejected? Did I forget to delete the remote branch after it is merged?
After some working with the repository, you'll execute git fetch --prune
or git remote update --prune
occasionally.
However, you'll likely see the mess of local branches whose upstreams are already merged and deleted on the remote.
Because git fetch --prune
only deletes remote-tracking branches (or remote references, refs/remotes/<remote>/<branch>
) but not local tracking branches (refs/heads/<branch>
) for you.
It is worse if remote branches that are merged but the maintainer forgot to delete them,
the remote-tracking branches would not be deleted and so on even if you know that it is merged into the master.
They are tedious to delete manually. git branch --merged
'll likely to betray you when branches are rebase merged or squash merged.
After the PR is merged or rejected, you're likely to delete them manually if you don't have git-trim
but it is tedious to type and error-prone.
You repeat these same commands as much as PRs that you've sent.
You have to remember what local branch is for the PR that just have been closed and it is easy to make a mistake.
I feel nervous whenever I put --force
flag. Rebase merge forces to me to use --force
(no pun is intended).
git reflog
is a fun command to play with, isn't it? Also git remote update
and git push
is not instantaneous.
I hate to wait for the prompt even it is a fraction of a second when I have multiple commands to type.
See FAQ
It is enough to type just git trim
and hit the y
key once.
Voila!
That's why I've made git-trim
.
It knows whether a branch is merged into the base branches, or whether it is rejected.
It can even push --delete
when you forgot to delete the remote branch if needed.
See --help
or docs
git fetch --prune only deletes remote-tracking branches (or remote references, refs/remotes/...
) when the remote branches are deleted.
The problem is that it doesn't touch local tracking branches that track the remote upstream branches
even if the upstreams are merged into the base and deleted by somehow. You should manually delete corresponding tracking branches in that case.
If you use rebase merge, you might have to use scary --force
flag such as git branch --delete --force
.
git-trim
does detect whether the upstream branches are merged into the upstream of the base branch.
It knows whether it is safe to delete, and even knows that you forgot to delete the remote branch after the merge.
Just deleting tracking branches whose upstreams are gone with -D
, which implies --force
,
needs an extra caution since it might delete contents that are not fully merged into the base or modified after being merged.
Not because --force
is dangerous. Just gone
doesn't mean it is fully merged to the base. So I gave it steroids, and it became git-trim
.
- It inspects the upstream of tracking branches whether they are 'fully' merged, not just whether they are gone. I've spent about half of the code on scenario tests. I wanted to make sure that it doesn't delete unmerged contents accidentally in any case.
- It supports github flow (master-feature tiered branch strategy), git flow (master-develop-feature tiered branch strategy), and simple workflow (with a remote repo and a local clone), and triangular workflow (with two remote repos and a local clone).
- It is merge styles agnostic. It can detect common merge styles such as merge with a merge commit, rebase/ff merge and squash merge.
- It can also inspect remote branches so it deletes them from remotes for you in case you've forgotten to.
- Moreover, it runs in parallel. Otherwise, large repos with hundreds of stale branches would've taken a couple of minutes to inspect whether they are merged.
- A classic merge with a merge commit with
git merge --no-ff
- A rebase merge with
git merge --ff-only
(Withgit cherry
equivalents) - A squash merge with
git merge --squash
(With this method: https://stackoverflow.com/a/56026209)
A merged branch is a branch whose upstream branch is fully merged onto the upstream of the base branch so you're not going to lose the changes.
In contrast, a stray branch is a branch that there is a chance to lose some changes if you delete it. Your PRs are sometimes rejected and deleted from the remote. Or you might have been mistakenly amended or rebased the branch and the patch is now completely different from the patch that is merged because you forgot the fact that the PR is already merged. Then they are not safe to delete blindly just because their upstreams are deleted. The term is borrowed from the git's remote tracking states.
Try this post-merge
hook. It automatically calls git trim --no-update
everytime you git pull
on master
or develop
. git config fetch.prune true
is recommended with this hook.
#!/bin/bash
BRANCH=$(git rev-parse --abbrev-ref HEAD)
case "$HEAD_BRANCH" in
"master"|"develop") ;;
*) exit ;;
esac
git trim --no-update
Or try git-sync
script. It pulls & prunes & trims in a single command.
I wanted to use prune
, stale
, but they are already taken.
Git and the Git logo are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries.
The logo is a derivative work of Git Logo. Git Logo by Jason Long is licensed under the Creative Commons Attribution 3.0 Unported License. The logo uses Bitstream Charter.
Images of a man with heartburn are generated with https://gvsc.rajephon.dev