Last Updated: September 09, 2019
·
2.641K
· evantahler

Delete old GIT branches already merged into master

(cross-post from http://blog.evantahler.com/delete-old-git-branches-already-merged-into-master)

It was time to clean up some old git branches at TaskRabbit today. It turned out that we had hundreds of branches that were “old”, and could be removed. What do I mean by “old”? As with many things, coming up with the proper definition is 1/2 the battle. At the end of the day, “old” meant “I have been merged into master, and contain no un-merged code” (where master is your integration branch).

When phrased this way, there are some systematic and simple ways to due some git pruning. Here’s a simple rake task:

namespace :git do

  desc "delete remote branches which have already been merged into master"
  task :clean_merged_branches do
    local_branches = `git branch`.split("\n").map{ |line| line.gsub("  ","") }
    raise "You need to be in master to start this game" unless local_branches.include?('* master')
    say_and_do("git fetch --prune")
    bad_branches = `git branch -r --merged`.split("\n").map{ |line| line.gsub("  ","") }
    bad_branches.each do |bad_branch|
      parts = bad_branch.split("/")
      remote = parts.shift
      if remote == "origin"
        branch = parts.join("/")
        next if branch =~ /^HEAD.*/
        next if branch == /^refs\/.*/
        next if branch == "master"
        next if branch == /.*staging.*/
        next if branch == /.*production.*/

        say_and_do("git branch -D #{branch}") if local_branches.include?(branch)
        say_and_do("git push origin :#{branch}")
      else
        puts "skipping #{bad_branch} because it doesn't have a remote of 'origin'"
      end
    end
  end
end

def say_and_do(stuff, explanation=nil)
  puts explanation if explanation
  puts " > #{stuff}"
  `#{stuff}`
end

The trick here is git fetch -r –merged command which does exactly what we want: tell me about the remote branches which have all been merged into my current branch, master. We simply collect those branches, and delete them locally (if they exist) and on origin.

The logic goes like this

  • Ensure I am in the master branch
  • git fetch –prune (clean up my local branch list according to remote’s list)
  • git fetch -r –merged (show me the branches which have been merged into the integration branch)
  • loop through those branches and delete them locally and remotely

Two other points of note:

  • It’s very likely that you will have some staging, test, and production branches which are either equivalent to or slightly behind your integration branch. You probably want to explicitly ignore those
  • If you have more than one remote branch setup (perhaps heroku for deployment or tddium for testing), you want to be sure to ignore any branch which isn’t from “origin”

2 Responses
Add your response

There's a nice tool from Arc90 that also does this: http://lab.arc90.com/2012/04/03/git-sweep/

over 1 year ago ·

(megusta)

over 1 year ago ·