fzf is amazing, and we can do amazing things with it. Things like being super smart about adding files to staging.

fzf works by taking in a list that is newline delimited. It will then give you an interface to make one (or more than one) choice on what to pipe to the next command.

Let’s start with this shell function:

a() {
  git add $(git status -s | awk '{ print $2 }' | fzf)
}

This will list all the files that are unstaged and allow you to pick one of them using fzf. That file will be staged.

fzf will take up the entire terminal screen. If you use tmux then it will split. The following function addresses this.

a() {
  if [ "$TMUX" = "" ]; then
    git add $(git status -s | awk '{ print $2 }' | fzf)
  else
    git add $(git status -s | awk '{ print $2 }' | fzf-tmux)
  fi
}

This works because when starting tmux it sets $TMUX to a non-empty value.

This works great as long as we only want to add one file at a time. If we want to pass multiple arguments on to git add then we can pass the -m flag to tmux. This tells tmux we want to either a) select a single entry with enter or b) select multiple entries with TAB:

a() {
  if [ "$TMUX" = "" ]; then
    git add $(git status -s | awk '{ print $2 }' | fzf -m)
  else
    git add $(git status -s | awk '{ print $2 }' | fzf-tmux -m)
  fi
}

We’re getting very close to something great. But just seeing a list of files may not always be good enough. Sometimes we want a preview of what unstaged changes exist within it.

fzf has another option here: --preview. It will run the command you specify, replacing {} with the selected line in fzf.

a() {
  if [ "$TMUX" = "" ]; then
    git add $(git status -s | awk '{ print $2 }' | fzf -m --preview 'git diff --color=always {}')
  else
    git add $(git status -s | awk '{ print $2 }' | fzf-tmux -m --preview 'git diff --color=always {}')
  fi
}

I’m always looking for ways to improve my git commands, so I won’t say this function is end game level. I will say that is has to be close, though.

I plan on doing articles for more of my git functions, but if you’re interested you can checkout my git.zsh file