Improving git workflow
Over the 8 years I’ve been using git, I’ve tried different GUIs and TUIs, but nothing really stuck with me (I’ll list a few below anyway). Some had a great UI but didn’t cover my whole workflow, while others had tons of commands but the user experience wasn’t that great. So I always ended up back in the terminal, either because it was faster or because the tool I was using didn’t support what I needed.
A couple of years ago I decided to go all in with git CLI and just keep improving my workflow over time.
At first I thought about making my config clean, adding comments, and publishing it on GitHub. But the reality is: people have very different ways of working with git, different shells, and their own mnemonic rules for shortcuts. So my config wouldn’t work out-of-the-box for most developers — they’d need to tweak it (and few would bother).
So instead, I decided to write this post and show how you can gradually improve your own git CLI workflow.
Aliases
The most important part of improving your workflow is to stop typing long commands every time. Even if you only do this, your life will already be much easier.
Start by creating aliases for the commands you use the most. You’ve got two options:
- Use git alias.
- Use aliases from your shell.
Personally, I don’t see much benefit in the first approach
since you still have to type git every time.
So all my examples use shell aliases.
Also, I’ll stick to bash for examples (though I actually use fish), since it’s easier to adapt bash config snippets to your shell than the other way around.
Start simple, with the basics:
alias gs="git status"
alias gc="git commit"
alias gl="git log"
alias gp="git push"
alias gpl="git pull"
I usually take the first letters of the command words,
so for example, git commit --amend becomes gca.
But feel free to follow your own mnemonic rules.
Don’t try to alias everything under the sun. I’ve done that and ended up forgetting half of them because:
- I didn’t actually use them that much.
- When I needed them, I couldn’t remember the alias I chose.
Once you’re comfortable, you can start adding shortcuts for more complex commands.
Here are a few I use a lot:
# Amend and automatically commit staged changes to the latest commit
alias gcah="git commit --amend --reuse-message=HEAD"
# Commit staged changes with a temporary message
alias gcmt="git commit --message '$(date '+[ci skip] %Y-%m-%d %H:%M:%S')'"
# Interactively rebase all master's commits that haven't been pushed yet
alias grio="git rebase --interactive origin/master"
You can check out my full git config on GitHub.
Make commands interactive
Working with git often means picking something from a list (branches to merge, commits to rebase, files to stage, etc.). It’s way nicer to select them interactively instead of typing or copy-pasting.
For that, I use fzf, a fuzzy finder for the terminal. It reads a list from STDIN, lets you select interactively, and prints the result to STDOUT. At first it might not seem that useful, but combined with git it makes things much smoother.
For example, let’s improve one of the most common actions: staging files.
Normally you’d do:
# List changed and new files
git status
# Stage some of them
git add foo/bar/a.txt foo/baz/new.txt
Typing paths gets old fast. Here’s an alias that makes it nicer:
alias gas="\
# Display all changed and new files
git status --porcelain=v1 | \
# Filter only those not staged yet
grep --invert-match --extended-regexp '^[MADR] ' | \
# Pipe the list to fzf
fzf \
# Use NUL instead of a newline char for line delimiter \
--print0 \
# Allow selecting multiple files \
--multi \
# Use exact match (instead of fuzzy) \
--exact \
# Display file changes in a preview window (you can scroll them with ⇧ Shift + ↑↓) \
--preview 'git diff --ignore-all-space --color -- {2} | tail -n +5' | \
# Strip the status field from all selected files (the first 4 chars) \
# macOS comes with preinstalled BSD version of cut which lacks needed options, \
# So in case you're a macOS user use gcut instead. \
cut --zero-terminated --characters=4- | \
# Finally, add the selected files \
xargs -0 git add -- \
"
(macOS users: replace cut with gcut since the default BSD version lacks options.)
Here’s how it looks in action:
Interactive rebase
git rebase lets you rearrange, combine, and edit commits.
But the default flow — editing a text file — isn’t very convenient.
git-interactive-rebase-tool makes this interactive. You can reorder and pick commits with keystrokes instead of editing text manually.
Example:
Git blame
I still haven’t found a good way to make git blame interactive in the terminal.
On the rare occasions I need it, I just use tig or GitHub’s blame view.
If you know of any good tools, let me know.
Other tools
If you don’t want to roll your own aliases and functions, check out these tools. They didn’t stick for me, but maybe they’ll work for you:
- tig — a TUI client with views for different git commands (log, blame, tree, etc.). I still use it sometimes for interactive blame.
- lazygit — another TUI client. Tried it for a while, didn’t click.
- magit — a git porcelain for Emacs. People say it can replace git CLI entirely if you’re an Emacs user. Worth a try.
There are also tons of GUI clients and editor plugins out there. But I don’t have much experience with them, so can’t recommend any.