Adding a command to list recently changed git branches (three ways)
#
I wanted to add a command to make it easy for me to see what branches I’d worked on recently. Between different projects, bugfixes, and code reviews, I end up switching branches a lot, and it can be hard to remember the names of the branches I need to polish up for submitting as a pull request and merging. It’s also useful to find branches that can be deleted.
This is a git command to show all the branches sorted by date descending (branch names may be changed to protect the innocent):
git for-each-ref --sort -committerdate refs/heads/
1b46ebacca9d6a4f49698b59577e21254471f6ac commit refs/heads/look/fp-email-on-first-completion
875686cd2b9db4fe45b24a96299f71933f6599fa commit refs/heads/master
9ef1d512fcc6e05dc5b80121e1e3768c011bb167 commit refs/heads/look/document-position-metadata
ed6df9b73e2c38d74ee3419c71ee488703c8cb27 commit refs/heads/look/fix-dp-500
7b130aceaeafe31077265b6a1b7cdabd1f8329d4 commit refs/heads/look/improve-document-position-caching
fcb726b5372255a3b1c50eac1c04cf5eda4587d4 commit refs/heads/look/remove-rails-4-caching-hacks
bd1f3df97cfd3dcbe9803770fd24944bed01f236 commit refs/heads/look/remove-rails-3-code
9b6bc693e5273cf3a7ddea1062462ae333c1bb6a commit refs/heads/look/fix-selenium-rails-4
c231b29f083b14d7cdb698e8f4d2be105bc32e45 commit refs/heads/look/fix-account-router
8d16a3868f8a12961ee8dbcaa383fae7a10ebcd8 commit refs/heads/look/handle-invalid-content-hash
fe50ecee84e6017dfa444bb426c4ac7c9929fa50 commit refs/heads/look/unknown-format-rails-4
3bfe056947a351151d0e3cf18a61f30e9e03209b commit refs/heads/look/pluck
e903be6d8f2a2a170d913b5e77801600ec49023d commit refs/heads/look/match-array
bb07270a5045c737f60530ca1d3b8b17e2cdf7bb commit refs/heads/look/fix-change-column
bca2a817b32395576fe2c10be53b02022689ba75 commit refs/heads/look/rails-4-fixes
70c6e053c89e066f1eed0038faa1834ca255b4d4 commit refs/heads/look/GET_LOCK-sucks
07176fb95a802a3ca5dfcce5d3757d9831ef7d52 commit refs/heads/look/refactor-query-execution
5cb599fc57c7729ea8ed76f62ccd930b774a4d9c commit refs/heads/engine_index_refactor
(... dozens of branches omitted ...)
Adding a bit of formatting makes and piping to head
makes the output easier to read:
git for-each-ref --format='%(committerdate:iso8601) %(committerdate:relative) %(refname)' --sort -committerdate refs/heads/ | head -15
2016-08-04 17:59:50 -0700 4 days ago refs/heads/look/fp-email-on-first-completion
2016-08-04 17:24:34 -0700 4 days ago refs/heads/master
2016-08-04 15:02:23 -0700 4 days ago refs/heads/look/document-position-metadata
2016-08-02 13:27:42 -0700 6 days ago refs/heads/look/fix-dp-500
2016-07-28 12:24:30 -0700 11 days ago refs/heads/look/improve-document-position-caching
2016-07-19 19:55:07 -0700 3 weeks ago refs/heads/look/remove-rails-4-caching-hacks
2016-07-19 18:45:06 -0700 3 weeks ago refs/heads/look/remove-rails-3-code
2016-07-19 18:07:56 -0700 3 weeks ago refs/heads/look/fix-selenium-rails-4
2016-07-19 15:03:15 -0700 3 weeks ago refs/heads/look/fix-account-router
2016-07-18 17:36:24 -0700 3 weeks ago refs/heads/look/handle-invalid-content-hash
2016-06-30 18:49:33 -0700 6 weeks ago refs/heads/look/unknown-format-rails-4
2016-06-29 19:18:17 -0700 6 weeks ago refs/heads/look/pluck
2016-06-29 19:17:18 -0700 6 weeks ago refs/heads/look/match-array
2016-06-29 11:17:49 -0700 6 weeks ago refs/heads/look/fix-change-column
2016-06-21 14:36:50 -0700 7 weeks ago refs/heads/look/rails-4-fixes
This is a lot of typing, though! The easiest way to shorten it is to create a Bash alias:
alias grecent="git for-each-ref --format='%(committerdate:iso8601) %(committerdate:relative) %(refname)' --sort -committerdate refs/heads/ | head -15"
However, I wanted to make this a new subcommand, because I have trouble remembering to use Bash aliases.
The first thing I looked into was using a Bash function:
function git() {
if [[ $@ == 'recent' ]]; then
command git for-each-ref --format='%(committerdate:iso8601) %(committerdate:relative) %(refname)' --sort -committerdate refs/heads/ | head -15
else
command git "$@"
fi
}
This intercepts invocation of the git
command. If the argument is recent
, it runs my command. Otherwise, it passes the arguments to the git command (the Bash command
builtin is used so it can call the real git). One thing I learned writing this is that getting the quoting right is super important.
That’s not the only way to do it, though!
You can also add a git alias. Since this version doesn’t take an argument, that’s fairly simple:
[alias]
recent = !git for-each-ref --format='%(committerdate:iso8601) %(committerdate:relative) %(refname)' --sort -committerdate refs/heads/ | head -15
Because I only want to show some of the recent items, I need to invoke the alias as a shell command using !
so I can use head
. You can also add arguments to git aliases, but it is a bit more complicated.
Another way is to add a new executable named git-recent
to your $PATH (Antonio Santos Velasco has a good tutorial about this.). This will enable you to type git recent
to invoke it. I have a ~/bin
directory that is on my path, so that is a pretty easy place to stash such a command. If you want to add argument parsing (for example, to change the default number of recent items), using a stand-alone script is probably the easiest way.
Here’s the full git-recent script:
#!/bin/bash
DEFAULT_ITEMS=15
ITEMS=${1-$DEFAULT_ITEMS}
git for-each-ref --format='%(committerdate:iso8601) %(committerdate:relative) %(refname)' --sort -committerdate refs/heads/ | head -$ITEMS
You can invoke it like this to get the default number of recent branches:
git recent
Or specify the number of branches:
git recent 10
Now that I have an easy way of listing recently changed branches, I use it constantly. It’s been super useful for me. Maybe it will be for you, too.