Skip to content

Instantly share code, notes, and snippets.

@zamber
Last active December 6, 2019 20:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zamber/3618f150084a0b3c221c11ef81e1036b to your computer and use it in GitHub Desktop.
Save zamber/3618f150084a0b3c221c11ef81e1036b to your computer and use it in GitHub Desktop.
How to remove merged branches

How to clean up Git branches

This will take a while to do.

  1. Make a new clone of your repo.

     git clone <repo> <repo>-bak
     cd <repo>-bak
    
  2. Make a backup of all branches locally in case you fuck up something.

     git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
     git fetch --all
     git pull --all
     # via https://stackoverflow.com/questions/10312521/how-to-fetch-all-git-branches#10312587
    
  3. List all remote branches, oldest first

     git for-each-ref --sort=committerdate refs/heads/ --format='%(committerdate:short) %(refname:short)'
     # via https://stackoverflow.com/a/16961359/1225741
    
  4. Add this to your .(zsh|bash)rc

     git-is-merged() {
         merge_destination_branch=$1
         merge_source_branch=$2
         merge_base=$(git merge-base $merge_destination_branch $merge_source_branch)
         merge_source_current_commit=$(git rev-parse $merge_source_branch)
         if [[ $merge_base == $merge_source_current_commit ]]; then
             echo $merge_source_branch
         fi
     }
     
     git-list-merged() {
         git for-each-ref --sort=committerdate refs/heads/ --format='%(committerdate:short) %(refname:short)' > /tmp/zsh-git-refs-temp
         while read line; do
             git-is-merged HEAD $(echo $line | awk -F" " '{print $2}')
             #echo $line
         done < /tmp/zsh-git-refs-temp
         rm /tmp/zsh-git-refs-temp
     }
     
     git-rm-merged() {
         git-list-merged | egrep --invert-match '(master|sprint)' > /tmp/zsh-git-refs-merged-HEAD
         while read line; do
             echo git push origin --delete $line
         done < /tmp/zsh-git-refs-merged-HEAD
         rm /tmp/zsh-git-refs-merged-HEAD
     }
    
  5. Source the changes in the rc file with . ~/.zshrc or . ~/.bashrc.

  6. Run git-rm-merged (it's non-destructive, it will echo out what it would do). Adjust the egrep to exclude branches that you want to leave untouched. Remove the echo if you feel confident about what will get deleted.

  7. Again source the file and run git-rm-merged :).

  8. Cleanup your rc file or restore the non-destructive version. Keep the repo in place for a couple months to have a way to restore branches if you did actually remove some that had to be left alone.

PS Tell me if it works on bash, I didn't test it there ;).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment