Skip to content

Instantly share code, notes, and snippets.

@mwerner
Created August 20, 2014 16:30
Show Gist options
  • Save mwerner/7900c655e9de0b40c37c to your computer and use it in GitHub Desktop.
Save mwerner/7900c655e9de0b40c37c to your computer and use it in GitHub Desktop.
git-clean
#! /usr/bin/env ruby
require 'rubygems'
require 'time'
require 'colorize'
require 'action_view'
require 'highline/import'
include ActionView::Helpers::DateHelper
include ActionView::Helpers::TextHelper
I18n.enforce_available_locales = false
action = ARGV[0]
term = ARGV[1]
origin = `git remote show -n origin | grep "Fetch URL:"`.match(/.*\:(.*)\./)[1]
sanitize = "grep -v master | sed \"s/ *origin\\///\" | sed \"s/ *tddium\\///\""
sanitize = "grep #{term} | #{sanitize}" unless term.nil?
branches = `git branch -r | #{sanitize}`.split("\n").uniq
merged = `git branch -r --merged master | #{sanitize}`.split("\n").uniq
unmerged = branches - merged
## Methods
def delete_branch(name)
print '!'.red
puts " Deleting: #{name}"
`git push origin :#{name}`
puts "Success!".green
end
def age_color(time)
return :red if time < Time.now - 4 * 7 * 24 * 60 * 60 # five weeks
return :light_yellow if time < Time.now - 1 * 7 * 24 * 60 * 60 # one week
return :green
end
def branch_info(name, origin)
info = {name: name, origin: origin, commits: {}, age: Time.now}; sha = nil
details = `git whatchanged --abbrev-commit master.. origin/#{name}`
details.split("\n").each do |line|
next if line.nil? || line == ''
checks = { name: 'commit', regex: /^commit\s(.*)/ },
{ name: 'author', regex: /^Author:\s(.*)\s</ },
{ name: 'timestamp', regex: /^Date:\s*(.*)$/ },
{ name: 'file', regex: /^:.*\s(.*)/ }
checks.each do |check|
val = line.match(check[:regex])
next if val.nil?
case check[:name].to_sym
when :commit
sha = val[1]
info[:commits][sha] ||= []
when :author
info[:author] = val[1]
when :file
info[:commits][sha] << val[1] unless sha.nil?
when :timestamp
committed_at = Time.parse(val[1])
info[:age] = committed_at if committed_at < info[:age]
end
end
end
info
end
def print_info(info)
files = info[:commits].values.flatten.uniq
puts "\n#{info[:name]}".send(age_color(info[:age]))
puts " #{info[:author]}"
puts " #{pluralize(info[:commits].keys.length, 'commit')} - #{distance_of_time_in_words_to_now(info[:age])} ago"
puts " #{files.first(5).join("\n ")}".light_black
if files.length > 5
puts " ...".light_black
puts " and #{files.length - 5} more...".light_black
end
puts " https://github.com/#{info[:origin]}/compare/#{info[:branch]}"
end
## Script
## Action: Status
if action == 'status'
print "Searching remote branches"
puts term.nil? ? ':' : " for \"#{term}\":"
if merged.length == 0
puts "\n> All remote branches that are merged have been deleted".green
else
puts "#{pluralize(merged.length, 'branch')} merged into master:".cyan
puts " #{merged.join("\n ")}"
end
if unmerged.length == 0
puts "\n> All unmerged remote branches have been deleted".green
else
puts "\n#{pluralize(unmerged.length, 'branch')} not been merged into master:".cyan
unmerged.each do |branch|
info = branch_info(branch, origin)
puts " #{info[:name].send(age_color(info[:age]))}"
end
end
exit
end
## Action: List ( default )
## List any outstanding merged branches
if action == 'list' || action.nil?
print "Searching remote branches"
puts term.nil? ? ':' : " for \"#{term}\":"
if merged.length == 0
puts "\n> All remote branches that are merged have been deleted".green
else
puts "#{pluralize(merged.length, 'branch')} merged into master:".green
puts " #{merged.join("\n ")}"
choice = ask("Delete all #{merged.length} branches? |(y)es, (n)o, (q)uit|".cyan)
exit if choice.strip == 'q'
merged.each{|branch| delete_branch(branch) } if choice.strip == 'y'
end
## Iterate through each outstanding unmerged branches
if unmerged.length == 0
puts "\n> All unmerged remote branches have been deleted".green
else
puts "\n#{pluralize(unmerged.length, 'branch')} not merged:"
print "RED ".red
puts " - Over a month old"
print "YELLOW".light_yellow
puts " - Over a week old"
print "GREEN ".green
puts " - Created this week"
unmerged.each do |branch|
print_info branch_info(branch, origin)
response = ask("Delete #{branch}? |(y)es, (n)o, (q)uit|".cyan)
exit if response.strip == 'q'
delete_branch(branch) if response.strip == 'y'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment