git changed-on-branch

2020-01-04

When I'm working on a branch, I naturally want to interact with the changed files. To make this easier, I wrote a custom git subcommand I've named git-changed-on-branch.

Invoked as git changed-on-branch, the script returns all changed filenames between your current branch and origin/master (though you can pass in an alternate comparison branch/sha/etc. as an argument if you wish).

Let's look at the thoroughly-commented code:

# !/bin/bash

# List files changed on the current branch versus a provided branch/sha/etc.
# (or the default of origin/master)
to_compare=${1:-origin/master}

(
  # First get already-committed file names that have been
  # (C)opied, (R)enamed, (A)added, or (M)odified
  #
  # We specify the diff-filter because we explicitly _don't_ care about Deleted
  # files.
  git diff ${to_compare}... --name-only --diff-filter=CRAM &&
  # Then get files that are currently modified (staged or unstaged)
  (git status --porcelain | awk '{print $2}')
) |
# Finally, remove duplicates without changing the sort order
awk '!x[$0]++'

Save that as git-changed-on-branch somewhere in $PATH and chmod +x. In typical Unix fashion, we can compose this in some interesting ways.

  • git changed-on-branch | grep test | xargs yarn jest could run your tests.
  • git changed-on-branch | fzf -m --height 40% | xargs -o vim from your shell uses fzf to select (one or more) files to be opened in vim.

Let your imagination run wild and make some helpful aliases.

As a closing example, here's how I use this within vim with fzf#run to open files changed on the branch:

nnoremap <silent> <Leader>gt :call fzf#run({
  \ 'source':  'git changed-on-branch',
\   'sink':    'e',
\   'options': '--multi --reverse',
\   'down':    15
\ })<CR>
My goofy face

Hi, I'm Jeffrey Chupp.
I solve problems, often with code.