Skip to content

Instantly share code, notes, and snippets.

@jsanders
Forked from thinkerbot/README.md
Created June 21, 2012 21:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsanders/2968558 to your computer and use it in GitHub Desktop.
Save jsanders/2968558 to your computer and use it in GitHub Desktop.
Find and remove old git branches

Description

Find and delete old git branches that are no longer needed.

Usage

Clone the repo and add to your path (just for ease of use):

git clone git://gist.github.com/2891516.git gist-2891516
cd gist-2891516
export PATH="$PATH:$(pwd)"

Now go to your project.

# list branches that have been merged to the current branch
git old-branches

# list branches that have been merged to the remote:
git old-branches github/master

# format branch delete commands according to user:
git old-branches github/master | format_branch_deletes

Example output:

$ git old-branches | format_branch_deletes
# schiang@comverge.com

  git branch -d remove_new_relic  # 301a52b (5 hours ago) <schiang@comverge.com>
  git branch -d something         # 301a52b (5 hours ago) <schiang@comverge.com>

$ git old-branches github/master | format_branch_deletes
# schiang@comverge.com

  git push github :30434977_fix_the_clock    # a262408 (3 weeks ago) <schiang@comverge.com>
  git push github :add_non_existant_methods  # f47c5c9 (10 days ago) <schiang@comverge.com>
  git push github :manual_requires           # c9bcc3f (3 weeks ago) <schiang@comverge.com>
  git push github :unnecessary_fsr           # 54f4eb4 (9 days ago) <schiang@comverge.com>

The idea is that you can check the delete commands and execute as needed. Note that once the remote branches are deleted your teammates may have to prune the deleted branches from their local copies:

# use --dry-run option first as a precaution
git remote prune github
#!/usr/bin/env ruby
begin
require 'optparse'
require 'erb'
require 'ostruct'
#############################################################################
OptionParser.new do |opts|
opts.banner = %{
Usage: #{$0} [options] [BRANCHES]
Formats a list of branches for deletion. If no branches are listed then
branches are read from stdin.
Local branches are formatted like
git branch -d BRANCH
Remote branches (remote/branch) are formatted like:
git push REMOTE :BRANCH
Options:
}.lstrip
opts.on("-h", "--help", "print this help") do
puts opts
puts
exit
end
end.parse!
#############################################################################
# read branches from stdin and sort by email
branches_by_email = Hash.new {|hash, key| hash[key] = [] }
while branch = gets
branch.strip!
logline = `git log --format="%ae,%h,%cr" -n1 '#{branch}'`
email, sha, date = logline.strip.split(',')
msg = "#{sha} (#{date}) <#{email}>"
if branch.include?('/')
remote, branch = branch.split('/')
else
remote = ""
end
branches_by_email[email] << [remote, branch, msg]
end
# print assignments
template = ERB.new <<-EOF, nil, "<>"
# <%= email %>
<% branches.sort.each do |(remote, branch, msg)| %>
<% if remote.empty? %>
git branch -d <%= branch.ljust(max) %> # <%= msg %>
<% else %>
git push <%= remote %> :<%= branch.ljust(max) %> # <%= msg %>
<% end %>
<% end %>
EOF
branches_by_email.keys.sort.each do |email|
branches = branches_by_email[email]
binding = OpenStruct.new(
:email => email,
:branches => branches,
:max => branches.map {|r,b,m| b.length }.max
).send(:binding)
puts template.result(binding)
end
#############################################################################
rescue(Errno::EPIPE)
raise if $DEBUG
if $!.class == Errno::EPIPE
exit 0
else
puts "#{$!.message} (see '#{$0} --help')"
exit 1
end
end
#!/bin/bash
############################################################################
progname="${0##*/}"
version="1.0"
author="Simon Chiang"
usestr="usage: %s [-h] [reference_branch]
Prints branches already merged to the reference branch (by default the
current branch). If a remote branch is given, then branches for that
remote are considered.
"
optstr=" %s %s\n"
while getopts "h" opt
do
case $opt in
d ) delete="true" ;;
h ) printf "$usestr" "$progname"
printf "%s" "$hel"
printf "options:\n"
printf "$optstr" "-h" "prints this help"
printf "\n"
exit 0 ;;
r ) remote="$OPTARG/" ;;
\? ) printf "$usestr" "$progname"
exit 2 ;;
esac
done
shift $(($OPTIND - 1))
############################################################################
current_branch () {
git branch | grep '*' | awk '{print $2}'
}
ref="${1:-$(current_branch)}"
remote=$(printf "%s" "$ref" | sed -ne 's/\/.*//p')
branch_opts=""
if ! [ x"$remote" = x ]
then branch_opts="-r"
fi
############################################################################
set -e
git branch $branch_opts --merged $ref |
tr -d '* ' |
grep "${remote:-.}" |
grep -v "^${ref}$" |
grep -v "^smartgrid-v.*-maint$"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment