How can I get a list of git branches, ordered by most recent commit?

I want to get a list of all the branches in a Git repository with the “freshest” branches at the top, where the “freshest” branch is the one that’s been committed to most recently (and is, therefore, more likely to be one I want to pay attention to).

Is there a way I can use Git to either (a) sort the list of branches by latest commit, or (b) get a list of branches together with each one’s last-commit date, in some kind of machine-readable format?

  • Connecting git branch to GitHub fork
  • git-svn and a large project
  • How to have Heroku build my development branch on a staging server?
  • Order branches in `git branch --all` by branch name
  • Keep settings in branch
  • How to branch and merge properly with Git?
  • Worst case, I could always run git branch to get a list of all the branches, parse its output, and then git log -n 1 branchname --format=format:%ci for each one, to get each branch’s commit date. But this will run on a Windows box, where spinning up a new process is relatively expensive, so launching the git executable once per branch could get slow if there are a lot of branches. Is there a way to do all this with a single command?

  • How to deny branching from master
  • Integrate RPGLE from GitHub to iSeries (IBM i)
  • How to verify SSH keys properly added for Git?
  • Squashing commits after they are pushed
  • Accessing git submodule in Android Studio
  • What is the 'standard' content of .gitignore for an iPhone (Xcode) project?
  • 21 Solutions collect form web for “How can I get a list of git branches, ordered by most recent commit?”

    Use --sort=-committerdate option of git for-each-ref;
    Also available since Git 2.7.0 for git branch:

    Basic Usage:

    git for-each-ref --sort=-committerdate refs/heads/
    
    # or using git branch (since version 2.7.0)
    git branch --sort=-committerdate  # DESC
    git branch --sort=committerdate  # ASC
    

    Result:

    result

    Advanced Usage:

    git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'
    

    Result:

    result

    To expand on Jakub’s answer and Joe’s tip, the following will strip out the “refs/heads/” so the output only displays the branch names:

    git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)'
    

    Tested!

    Here’s the optimal code, which combines the other two answers:

    git for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(authorname) %(refname:short)'
    

    Here is a simple command that lists all branches with latest commits:

    git branch -v
    

    To order by most recent commit, use

    git branch -v --sort=committerdate
    

    Source: http://git-scm.com/book/en/Git-Branching-Branch-Management

    I also needed colors, tags and remote references without any duplicates:

    for ref in $(git for-each-ref --sort=-committerdate --format="%(refname)" refs/heads/ refs/remotes ); do git log -n1 $ref --pretty=format:"%Cgreen%cr%Creset %C(yellow)%d%Creset %C(bold blue)<%an>%Creset%n" | cat ; done | awk '! a[$0]++'
    

    Because quoting can be hard, here the alias for bash:

    alias glist='for ref in $(git for-each-ref --sort=-committerdate --format="%(refname)" refs/heads/ refs/remotes ); do git log -n1 $ref --pretty=format:"%Cgreen%cr%Creset %C(yellow)%d%Creset %C(bold blue)<%an>%Creset%n" | cat ; done | awk '"'! a["'$0'"]++'"
    

    I use the following alias:

    recent = "!r(){git for-each-ref --sort=-committerdate refs/heads --format='%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)'|column -ts'|'}; r"

    which produces:
    result

    Edit: use ‘|’ to separate, thanks to @Björn Lindqvist

    Update: added * before the current branch, thanks to @elhadi
    Edit: fixed a case where the current branch was a substring of another branch

    Edit: use a simpler syntax for the current branch, thanks to @Joshua Skrzypek

    The other answers don’t seem to allow passing -vv to get verbose output.

    So here’s a one-liner that sorts git branch -vv by commit date, preserving color etc:

    git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ct $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ct)"\t$REPLY"; done | sort -r | cut -f 2
    

    If you additionally want to print the commit date, you can use this version instead:

    git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ci $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ci)" $REPLY"; done | sort -r | cut -d ' ' -f -1,4-
    

    Sample output:

    2013-09-15   master                  da39a3e [origin/master: behind 7] Some patch
    2013-09-11 * (detached from 3eba4b8) 3eba4b8 Some other patch
    2013-09-09   my-feature              e5e6b4b [master: ahead 2, behind 25] WIP
    

    It’s probably more readable split into multiple lines:

    git branch -vv --color=always | while read; do
        # The underscore is because the active branch is preceded by a '*', and
        # for awk I need the columns to line up. The perl call is to strip out
        # ansi colors; if you don't pass --color=always above you can skip this
        local branch=$(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g')
        # git log fails when you pass a detached head as a branch name.
        # Hide the error and get the date of the current head.
        local branch_modified=$(git log -1 --format=%ci "$branch" 2> /dev/null || git log -1 --format=%ci)
        echo -e "$branch_modified $REPLY"
    # cut strips the time and timezone columns, leaving only the date
    done | sort -r | cut -d ' ' -f -1,4-
    

    This should also work with other arguments to git branch, e.g. -vvr to list remote-tracking branches, or -vva to list both remote-tracking and local branches.

    git 2.7 (Q4 2015) will introduce branch sorting using directly git branch:
    See commit aa3bc55, commit aedcb7d, commit 1511b22, commit f65f139, … (23 Sep 2015), commit aedcb7d, commit 1511b22, commit ca41799 (24 Sep 2015), and commit f65f139, … (23 Sep 2015) by Karthik Nayak (KarthikNayak).
    (Merged by Junio C Hamano — gitster — in commit 7f11b48, 15 Oct 2015)

    In particular, commit aedcb7d:

    branch.c: use ‘ref-filter‘ APIs

    Make ‘branch.c‘ use ‘ref-filter‘ APIs for iterating through refs sorting. This removes most of the code used in ‘branch.c‘ replacing it
    with calls to the ‘ref-filter‘ library.

    It adds the option --sort=<key>:

    Sort based on the key given.
    Prefix - to sort in descending order of the value.

    You may use the --sort=<key> option multiple times, in which case the last key becomes the primary key.

    The keys supported are the same as those in git for-each-ref.
    Sort order defaults to sorting based on the full refname (including refs/... prefix). This lists detached HEAD (if present) first, then local branches and finally remote-tracking branches.

    Here:

    git branch --sort=-committerdate 
    

    See also commit 9e46833 (30 Oct 2015) by Karthik Nayak (KarthikNayak).
    Helped-by: Junio C Hamano (gitster).
    (Merged by Junio C Hamano — gitster — in commit 415095f, 03 Nov 2015)

    When sorting as per numerical values (e.g. --sort=objectsize) there is no fallback comparison when both refs hold the same value. This can cause unexpected results (i.e. the order of listing refs with equal values cannot be pre-determined) as pointed out by Johannes Sixt ($gmane/280117).

    Hence, fallback to alphabetical comparison based on the refname
    whenever the other criterion is equal
    .

    $ git branch --sort=objectsize
    
    *  (HEAD detached from fromtag)
          branch-two
          branch-one
          master
    

    I like using a relative date and shortening the branch name like this:

    git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads
    

    Which gives you output:

    21 minutes ago  nathan/a_recent_branch
    6 hours ago     master
    27 hours ago    nathan/some_other_branch
    29 hours ago    branch_c
    6 days ago      branch_d
    

    I recommend making a bash file for adding all your favorite aliases and then sharing the script out to your team. Here’s an example to add just this one:

    #!/bin/sh
    
    git config --global alias.branches "!echo ' ------------------------------------------------------------' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------'"
    

    Then you can just do this to get a nicely formatted and sorted local branch list:

    git branches
    

    Update:
    Do this if you want coloring:

    #!/bin/sh
    #
    (echo ' ------------------------------------------------------------‌​' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------‌​') | grep --color -E "$(git rev-parse --abbrev-ref HEAD)$|$"
    

    Adds some color (since pretty-format isn’t available)

    [alias]
        branchdate = for-each-ref --sort=-committerdate refs/heads/ --format="%(authordate:short)%09%(objectname:short)%09%1B[0;33m%(refname:short)%1B[m%09"
    

    FYI, if you’d like to get a list of recently checked out branches (as opposed to recently committed) you can use git’s reflog:

    $ git reflog | egrep -io "moving from ([^[:space:]]+)" | awk '{ print $3 }' | head -n5
    master
    stable
    master
    some-cool-feature
    feature/improve-everything
    

    See also: How can I get a list of git branches that I've recently checked out?

    I had the same problem, so I wrote a Ruby gem called Twig. It lists branches in chronological order (newest first), and can also let you set a max age so that you don’t list all branches (if you have a lot of them). For example:

    $ twig
    
                                  issue  status       todo            branch
                                  -----  ------       ----            ------
    2013-01-26 18:00:21 (7m ago)  486    In progress  Rebase          optimize-all-the-things
    2013-01-26 16:49:21 (2h ago)  268    In progress  -               whitespace-all-the-things
    2013-01-23 18:35:21 (3d ago)  159    Shipped      Test in prod  * refactor-all-the-things
    2013-01-22 17:12:09 (4d ago)  -      -            -               development
    2013-01-20 19:45:42 (6d ago)  -      -            -               master
    

    It also lets you store custom properties for each branch, e.g., ticket id, status, todos, and filter the list of branches according to these properties. More info: http://rondevera.github.io/twig/

    I was able to reference the examples above to create something that works best for me.

    git for-each-ref –sort=-committerdate refs/heads/
    –format=’%(authordate:short) %(color:red)%(objectname:short) %(color:yellow)%(refname:short)%(color:reset)
    (%(color:green)%(committerdate:relative)%(color:reset))’

    Screenshot of Output

    Here is another script that does what all the other scripts do. In fact, it provides a function for your shell.

    Its contribution is that it pulls some colours from your git config (or uses defaults).

    # Git Branch by Date
    # Usage: gbd [ -r ]
    gbd() {
        local reset_color=`tput sgr0`
        local subject_color=`tput setaf 4 ; tput bold`
        local author_color=`tput setaf 6`
    
        local target=refs/heads
        local branch_color=`git config --get-color color.branch.local white`
    
        if [ "$1" = -r ]
        then
            target=refs/remotes/origin
            branch_color=`git config --get-color color.branch.remote red`
        fi
    
        git for-each-ref --sort=committerdate $target --format="${branch_color}%(refname:short)${reset_color} ${subject_color}%(subject)${reset_color} ${author_color}- %(authorname) (%(committerdate:relative))${reset_color}"
    }
    

    My best result as a script:

    git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short)|%(committerdate:iso)|%(authorname)' |
        sed 's/refs\/heads\///g' |
        grep -v BACKUP  | 
        while IFS='|' read branch date author
        do 
            printf '%-15s %-30s %s\n' "$branch" "$date" "$author"
        done
    

    Based on ilius’ version, but with the current branch shown with a star and in color, and only showing anything that is not described as “months” or “years” ago:

    current_branch="$(git symbolic-ref --short -q HEAD)"
    git for-each-ref --sort=committerdate refs/heads \
      --format='%(refname:short)|%(committerdate:relative)' \
      | grep -v '\(year\|month\)s\? ago' \
      | while IFS='|' read branch date
        do
          start='  '
          end=''
          if [[ $branch = $current_branch ]]; then
            start='* \e[32m'
            end='\e[0m'
          fi
          printf "$start%-30s %s$end\\n" "$branch" "$date"
        done
    

    Here’s the variation I was looking for:

    git for-each-ref --sort=-committerdate --format='%(committerdate)%09%(refname:short)' refs/heads/ | tail -r
    

    That tail -r reverses the list so the most-recent commiterdate is last.

    Late to the party here. The accepted CML answer rocks, but if you want something prettier, like a GUI, and your origin === “github”.

    You can click “Branches” in the repo. or hit the url direct: https://github.com/ORGANIZATION_NAME/REPO_NAME/branches

    I pipe the output from the accepted answer into dialog, to give me an interactive list:

    #!/bin/bash
    
    TMP_FILE=/tmp/selected-git-branch
    
    eval `resize`
    dialog --title "Recent Git Branches" --menu "Choose a branch" $LINES $COLUMNS $(( $LINES - 8 )) $(git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short) %(committerdate:short)') 2> $TMP_FILE
    
    if [ $? -eq 0 ]
    then
        git checkout $(< $TMP_FILE)
    fi
    
    rm -f $TMP_FILE
    
    clear
    

    Save as (e.g.) ~/bin/git_recent_branches.sh and chmod +x it. Then git config --global alias.rb '!git_recent_branches.sh' to give me a new git rb command.

    Here’s a little script that I use to switch between recent branchs:

    #!/bin/bash
    # sudo bash
    
    re='^[0-9]+$'
    
    if [[ "$1" =~ $re ]]; then
        lines="$1"
    else
        lines=10
    fi
    branchs="$(git recent | tail -n $lines | nl)"
    branchs_nf="$(git recent-nf | tail -n $lines | nl)"
    echo "$branchs"
    
    # Prompt which server to connect to
    max="$(echo "$branchs" | wc -l)"
    index=
    while [[ ! ( "$index" =~ ^[0-9]+$ && "$index" -gt 0 && "$index" -le "$max" ) ]]; do
        echo -n "Checkout to: " 
        read index
    done
    
    branch="$( echo "$branchs_nf" | sed -n "${index}p" | awk '{ print $NF }' )"
    git co $branch
    clear
    

    Using those two aliases

    recent = for-each-ref --sort=committerdate refs/heads/ --format=' %(color:blue) %(authorname) %(color:yellow)%(refname:short)%(color:reset)'
    recent-nf = for-each-ref --sort=committerdate refs/heads/ --format=' %(authorname) %(refname:short)'
    

    Just call that in a git repo and it will show you the last N branches (10 by default) and a number aside each. Input the number of the branch and it checks out.

    I came up with the following command:

    git branch -r --sort=creatordate \
        --format "%(creatordate:relative);%(committername);%(refname:lstrip=-1)" \
        | grep -v ";HEAD$" \
        | column -s ";" -t
    

    If you don’t have column you can replace the last line with

        | sed -e "s/;/\t/g"
    

    The output looks like

    6 years ago             Tom Preston-Werner  book
    4 years, 4 months ago   Parker Moore        0.12.1-release
    4 years ago             Matt Rogers         1.0-branch
    3 years, 11 months ago  Matt Rogers         1.2_branch
    3 years, 1 month ago    Parker Moore        v1-stable
    12 months ago           Ben Balter          pages-as-documents
    10 months ago           Jordon Bedwell      make-jekyll-parallel
    6 months ago            Pat Hawks           to_integer
    5 months ago            Parker Moore        3.4-stable-backport-5920
    4 months ago            Parker Moore        yajl-ruby-2-4-patch
    4 weeks ago             Parker Moore        3.4-stable
    3 weeks ago             Parker Moore        rouge-1-and-2
    19 hours ago            jekyllbot           master
    

    I wrote a blog post about how the various pieces work.

    Git Baby is a git and github fan, let's start git clone.