DEV Community

Peter Benjamin (he/they)
Peter Benjamin (he/they)

Posted on • Updated on

Print Git Status in Your Tmux Statusbar

Table of Contents

Problem

I recently wanted to show git branch and status information of the project I am wokring on in tmux statusbar.

We can use one of the many open source projects to achieve this (see the Conclusion for honorable mentions), but I prefer a minimalist approach for simplicity and portability.

Naturally, I know I can invoke any shell command from my .tmux.conf using the #(<shell command>) syntax.

For example, set -g status-right '#(echo "hello world")' will print hello world in the right corner of your tmux statusbar, which is located at bottom by default.

But, doing something like set -g status-right '#(git branch)' didn't work. This is because the command is running in a different shell context, like running sh -c "git branch". The current directory is simply not passed to the sub-shell command.

Furthermore, git branch only prints the branch name. We need a custom bash function to print symbols indicating if there are modified files, staged files, stashes, and/or untracked files.

Solution

Similar to how you can print any information in a .bash_prompt via custom bash functions, so too can we implement a function that is invoked as a git sub-command via aliases.

Bash Function

The function we will use for this is borrowed from jessfraz/dotfiles.

If we simply join all the lines and escape the double-quotes, it looks like this:

prompt_git() { local s=''; local branchName=''; if [ \"$(git rev-parse --is-inside-work-tree &>/dev/null; echo \"${?}\")\" == '0' ]; then if [ \"$(git rev-parse --is-inside-git-dir 2> /dev/null)\" == 'false' ]; then if [[ -O \"$(git rev-parse --show-toplevel)/.git/index\" ]]; then git update-index --really-refresh -q &> /dev/null; fi; if ! git diff --quiet --ignore-submodules --cached; then s+='+'; fi; if ! git diff-files --quiet --ignore-submodules --; then s+='!'; fi; if [ -n \"$(git ls-files --others --exclude-standard)\" ]; then s+='?'; fi; if git rev-parse --verify refs/stash &> /dev/null; then s+='$'; fi; fi; branchName=\"$(git symbolic-ref --quiet --short HEAD 2> /dev/null || git rev-parse --short HEAD 2> /dev/null || echo '(unknown)')\"; echo \"(${1}${branchName} ${s})\"; else return; fi; }
Enter fullscreen mode Exit fullscreen mode

Git Alias

Now, you can put this one-liner into a git alias in your .gitconfig or ~/.config/git/config, like this:

[alias]
    prompt = !"prompt_git() { ... }; prompt_git"
Enter fullscreen mode Exit fullscreen mode

Tip: alternatively, you can copy/paste the bash_prompt function into a shell script file prefixed with git-, like git-prompt, placed somewhere in your $PATH. This allows you to call it as if it were a standard git subcommand as well, like git prompt.

Note that we invoke/execute the function after defining it.

To test this, simply run:

$ git prompt
Enter fullscreen mode Exit fullscreen mode

It should return the branch name and indicators based on your status, like:

(branch +!$?)
Enter fullscreen mode Exit fullscreen mode

Tmux

Now, we can easily call a git command to show this information, but we also need to pass a -C flag with a path to the repo in question. Fortunately, tmux gives us the path of the current pane in a special variable called #{pane_current_path}.

So, our status bar configuration in tmux may look like:

set -g status-right '#(git -C #{pane_current_path} prompt)'
Enter fullscreen mode Exit fullscreen mode

Bonus Tip

Did you know tmux has 2 different "status bars"?

I like to put any global information, or information that does not change between panes, in my status-right. This includes date, time, cpu, and memory.

Any pane-specific information, I prefer to put it in my pane-border-format. This includes current working directory and git status information.

Example:

set -g status-right-length 200
# show [prefix] when activated/pressed + mem/cpu load + date/timestamp
set -g status-right "#{?client_prefix,#[reverse][prefix]#[noreverse],}  #(tmux-mem-cpu-load --interval 1) [%A %Y-%m-%d %l:%M %p]"

set -g pane-border-status top
set -g pane-border-format ' #{pane_current_path} #(git -C #{pane_current_path} prompt) '
Enter fullscreen mode Exit fullscreen mode

Conclusion

If you are a minimalist like me, I hope this helps you configure and customize your tmux to best suit your needs, workflow, and productivity.

If you were hoping to discover tools or utilities to conveniently configure tmux, then I would like to leave you with some honorable mentions:

  • gitmux: a binary that you can simply download, configure, and execute in your .tmux.conf. No runtime dependencies needed.
  • powerline: a fully-featured statusline utility for vim, tmux, and more. Requires python.
  • tmux-git: a tmux plugin.

For more inspiration, feel free to browse my dotfiles.

Thank you for reading.

Happing hacking!

Discussion (0)