This page looks best with JavaScript enabled

Git: autocomplete –trailer and –cc in zsh

 ·   ·  ☕ 3 min read  ·  ✍️  Firmin Martin

Introduction

When working on a Git repository developped through email-based workflow (e.g. Git, Linux kernel, Emacs, notmuch etc.), it is often needed

  • to git commit with the --trailer option to acknowledge people,
  • and to git send-email with the --to & -cc options to indicate the recipients of the patch series to send.

Newcomers of such workflow, as me, would copy one by one the email addresses from git-log or the project mailing list at the beginning. But it becomes quickly tiresome. The good news is that this process can be automatized with fzf and zsh (see the Screencasts section).

Let’s make a fake Git repository to illustrate how it works. The following snippet will create at most 1500 empty commits from 150 distinct developers. It uses rig1 to create fake identities.

1
2
3
4
5
6
7
8
DIR=~/tmp/Git_fzf/ mkdir -p $DIR && cd $DIR
git init
rig -c 150 | awk -v RS='\n\n' '{print $1 " " $2}' |
    while read name; do
        for i in {1..$(( RANDOM % 10 + 1 ))}; do
            git commit --author "$name <${${name// /.}:l}@domain.com>" --allow-empty --allow-empty-message -m "";
        done
    done

Figure 1: Creating a fake Git repository with distinct authors.

Figure 1: Creating a fake Git repository with distinct authors.

Fetching email addresses of developers

The following command returns all email addresses of the current Git repository’s developers.

1
git shortlog -sne --all | cut -f2

Breaking it down, we instruct git shortlog

  • to suppress commit descriptions (-s),
  • to sort the contributors by the number of commits (-n),
  • to provide contributors' email (-e),
  • and to consider the developers of all branches (--all).

Piping the result to cut -f2 helps us to get rid of the commits count.

Select email addresses

Now, we want to pick out some addresses we are interested in. This step requires that the fuzzy filter fzf is installed.

It’s pretty simple: we just have to pipe the result of git-shortlog to fzf and use the option -m to enable multiple choices. The --reverse option makes a drop-down menu which I find less disruptive.

1
git shortlog -sne --all | cut -f2 | fzf -m --reverse

Now you can select/unselect emails with TAB / Shift+TAB. Once you are done, press RET. It will output the selected entries.

Select git-commit trailers and git-send-email recipients options

We can also make a drop-down menu to select git-commit trailers and recipients options. Let’s wrap it in a function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
__fzf_git_trailer_and_option() {
cat <<- EOF | fzf --reverse
	--to=
	--bcc=
	--cc=
	--trailer Thanks-to:
	--trailer Reviewed-by:
	--trailer Reported-by:
	--trailer Acked-by:
	--trailer Tested-by:
	--trailer Based-on-patch-by:
	--trailer Mentored-by:
	EOF
}

Detect if we are under a Git repository

The command git rev-parse --is-inside-work-tree can tell whether we are under a Git repository. Let’s enable autocompletion only in such situation. We wrap this into a function which, given a selected trailer or option and potentially multiple addresses, returns addresses prefixed by the selected trailer or option.

1
2
3
4
5
6
7
8
9
__fzf_git_authors() {
  if $(git rev-parse --is-inside-work-tree 2>/dev/null); then
    local trailer_or_option=$(__fzf_git_trailer_and_option)
    git shortlog -sne --all | cut -f2 | fzf -m --reverse |
        while read item; do
                echo -n "${trailer_or_option}'${item}' "
        done
   fi
}

Bind autocompletion to a shortcut

So far, the result is outputted to the terminal, but we actually want that it appends the current command line. So, we keep the content on the left of the buffer and redisplay it.

1
2
3
4
5
fzf-git-authors() {
  LBUFFER="${LBUFFER}$(__fzf_git_authors)"
  zle redisplay
  typeset -f zle-line-init >/dev/null && zle zle-line-init
}

Finally, I bound that function to Alt-E.

1
2
zle     -N   fzf-git-authors
bindkey '\ee' fzf-git-authors

Screencasts

Figure 2: git-commit with --trailer autocompletion.

Figure 2: git-commit with --trailer autocompletion.

Figure 3: git-send-email with recipients autocompletion.

Figure 3: git-send-email with recipients autocompletion.


  1. On Ubuntu, sudo apt install rig↩︎


Firmin Martin
WRITTEN BY
Firmin Martin

What's on this Page