Often, some projects using git have too many branches, but most branches are not updated in days. The old branches are very bother.
I wrote a script which shows only recent branches named 'git-branch-recent'.
#!/usr/bin/env ruby -Ku require 'pathname' require "optparse" class GitRecentCommand Ref = Struct.new(:hash, :name, :time, :rtime, :author, :subject) def dot_git @dot_git ||= Pathname.new(`git rev-parse --git-dir`.chomp) end def self.run(argv) self.new.option(argv).run end def initialize(opts={}) @opts = { :strict => false, :max_num => 20, }.update(opts) end def option(argv) opts = @opts argv = argv.dup OptionParser.new do |parser| parser.instance_eval do self.banner = <<-EOB.gsub(/^\t+/, "") Usage: #{$0} [opts] EOB separator "" separator "Options:" on("-s", "--strict", "Running on strict mode (very heavy)") do |foreground| opts[:strict] = true end on("-n", "--number NUMBER", "Number branch to show") do |num| opts[:max_num] = num.to_i end parse!(argv) end end self end def run details = @opts[:strict] ? recent_branches_strict : recent_branches_fast details = details.sort_by {|ref| ref.time }.last(@opts[:max_num]) remote_master = nil rtime_width = name_width = author_width = 0 details.each do |ref| name_width = ref.name.size if ref.name.size > name_width author_width = ref.author.size if ref.author.size > author_width rtime_width = ref.rtime.size if ref.rtime.size > rtime_width remote_master = ref.hash if ref.name == 'origin/master' end details.each {|ref| ref.instance_eval { out = "\e[32m% -#{name_width}s\e[39m % #{rtime_width}s %s \e[31m% -#{author_width}s\e[39m %s" % [ name, rtime, hash[/^.{7}/], author, subject ] puts (hash == remote_master) ? "\e[7m#{out}\e[0m" : out } } end # search recent branches by file mtimes def recent_branches_fast refs = [] refs.concat Pathname.glob(dot_git + 'refs/heads/**/*') refs.concat Pathname.glob(dot_git + 'refs/remotes/**/*') branches = refs.reject {|r| r.directory? }.sort_by {|r| r.mtime }.last(@opts[:max_num]).map {|r| ref = r.read.chomp if name = ref[/ref: (.+)/, 1] (dot_git + name).read.chomp else ref end } retrieve_branch_details(branches) end # search recent branches by retrieving whole branch information def recent_branches_strict branches = `git branch -a`.gsub!(/^\*?\s+|\(no branch\)\s*/, "").split(/\n/).map {|i| i.split(/ -> /)[0] } retrieve_branch_details(branches) end # retrieve branch details information from branch names def retrieve_branch_details(branches) details = [] IO.popen("-", "r+") do |io| if io.nil? args = [ "show", "--pretty=format:%H\t%d\t%ct\t%cr\t%an\t%s", *branches ] args << "--" exec "git", *args else while l = io.gets next unless l =~ /^[a-z0-9]{40}/ hash, refs, time, rtime, author, subject = * l.chomp.split(/\t/) refs.gsub!(/^\s*\(|\)\s*$/, '') refs.split(/\s*,\s*/).each do |ref| is_remote = ref[%r{refs/remotes}] ref.gsub!(%r{refs/(remotes|heads)/}, '') details.push Ref.new(hash, ref, time.to_i, rtime, author, subject) end end end end details end end GitRecentCommand.run(ARGV)
[[git]]