Git aliases for fun and profit
"Git gets easier once you grasp the basic idea that branches are homeomorphic endofunctors, mapping submanifolds of a Hilbert space." - Anonymous

The Lun-class Ekranoplan was a 280,000-kilogram Soviet-era, cruise-missile mounted seaplane
Sometimes working with Git feels like what I imagine being a solo captain of the 280,000 kilogram Lun-class ekranoplan would feel like, which incidentally is the only ground-effect vehicle to ever be operationally mobilised as a warship, deploying in the Caspian Flotilla. It was designed in 1975 by Rostislav Alexeyev of what later became the Alekseyev Central Hydrofoil Design Bureau, and it was used by the Soviet (and later, Russian) navies from 1987 until the late 1990s. It required a crew of 15 career naval officers to operate.
I occasionally think that personally stealing and attempting to commandeer the largest piece of Soviet-era marine aeronautics machinery of all time would deliver a less ergonomically hostile experience than Git; a computer tool that most software developers need only 4 commands from in order to save their work to the Internet.
I know what you're going to say:
"You just don't know how to use Git." - Git Enjoyers
False. I do know how to use Git. The problem is that I am a person that both knows how to use Git and believes that a better world is possible; a complex psychological position that requires two separate and orthogonal systems of thought to exist in harmony with one another. Anyway. I do also sometimes quite like Git, so my thoughts on this issue are mixed and many, and influenced strongly by whether or not I am enjoying programming computers that day. Plus, I'm being deliberately facetious because I want to write about the Ekranoplan. Git is absurdly powerful, and as a result, is sometimes hard. It solves a nasty problem that is deceptively complicated in a way that I suspect is still the best of all of the big version control systems. The fact that it dominates in spite of its DX is a testament to it's utility.
Arcane computer incantations
This article is less about my personal vendetta against arcane computer incantations and more about some of the small ways I've found to improve that experience for myself and as such, remain employed. Some part of that is writing aliases. Hilariously, even the aliases web page in some way reads like an ancient scroll, and the documentation in general is in some places sufficiently obscure that it spawned it's own excellent parody - indistinguishable from some of the actual documentation.
Simply put, Git aliases are custom shortcuts that you create to replace longer Git commands with
shorter, easier-to-remember alternatives. They're essentially abbreviations you define in your
.gitconfig file that let you type something brief like git st
instead
of git status --short --branch
. Considering that the vast majority of software
engineers never use more than about 15 git commands in their career, and my personal memory in the
category of 'insane computer syntax' is a disaster, with enough of these aliases, I've been able to
build a small collection of utilities that let me do almost everything I regularly need to, without
having to read the documentation very often.
This collection is really for developers who've moved beyond the basics of pulling, branching, committing and pushing, and want to streamline their general Git workflow. They cover fairly common cases that save me both keystrokes and mental overhead. I'm sharing them here with you in case they're also useful for you!
If you want to, you can copy any (or all) of them in one go, later in the article.
The collection
git aa
StagingPurpose: Stage all changes, including new and deleted files. Basically a git add . shortcut.
What do I put in [alias]?
aa = add --all
Use it like this: git aa
git big-mad
Cleanup | ⚠️Purpose: Completely undo your last commit and discard all changes. This resets your branch to the previous commit.
What do I put in [alias]?
big-mad = reset --hard HEAD^
(This is useful when you want to pretend a commit never happened, not just clear your working directory. Important: Only use uh on branches that haven't been pushed or shared with others, as it deliberately rewrites history.)
Use it like this: git big-mad
git br
Branch ManagementPurpose: List all remote branches at once. Good for seeing what's on the upstream.
What do I put in [alias]?
br = branch -r
Use it like this: git br
git bv
Branch ManagementPurpose: Show local branches with some useful tracking and last commit info.
What do I put in [alias]?
bv = branch -vv
Use it like this: git bv
git ca
Commit ManagementPurpose: Instantly amend your last commit.
What do I put in [alias]?
ca = commit --amend
(This will open your default editor with the previous commit message, allowing you to modify it if needed. When you save and close the editor, your previous commit will be replaced with a new one containing both the original changes and your new changes, along with the new commit message.)
Use it like this: git ca
git ci
Commit ManagementPurpose: Commit all staged and tracked changes, with a diff preview.
What do I put in [alias]?
ci = commit -a -v
Use it like this: git ci -m "Add new feature"
git cm
Commit Management | ⚠️Purpose: Amend the last commit with all current changes while keeping the original commit message.
What do I put in [alias]?
cm = commit -a --amend -C HEAD
Use it like this: git cm
git cp
Branch ManagementPurpose: Cherry-pick a specific commit onto your current branch.
What do I put in [alias]?
cp = cherry-pick
Use it like this: git cp a1b2c3d
git dm
ReviewPurpose: See a colorized summary of files changed on your current branch, compared to the main branch.
What do I put in [alias]?
dm = "!sh -c 'echo; git diff --name-status --diff-filter=ADM origin/main...$(git rev-parse --abbrev-ref HEAD) | sed -e \"s/^A/\\x1b[32mA\\x1b[0m/\" -e \"s/^M/\\x1b[33mM\\x1b[0m/\" -e \"s/^D/\\x1b[31mD\\x1b[0m/\"; echo; echo -e \"\\x1b[94mPaths changed: $(git diff --name-status --diff-filter=ADM origin/main...$(git rev-parse --abbrev-ref HEAD) | wc -l)\\x1b[0m\"'"
(Cool for working out exactly in what way your local branch is different to that of main.)
Use it like this: git dm
git force-safe
Collaboration | ⚠️Purpose: Safely force-push your branch, provided no one else has pushed to the branch since your last pull.
What do I put in [alias]?
force-safe = push --force-with-lease
Use it like this: git force-safe origin feature/branch
git graph
Log/HistoryPurpose: View a compact, visual commit graph showing all branches and their relationships.
What do I put in [alias]?
graph = log --oneline --graph --decorate --all
Use it like this: git graph
git last
Log/HistoryPurpose: Show details of your latest commit including changed files.
What do I put in [alias]?
last = log -1 HEAD --stat
Use it like this: git last
git ld
Log/HistoryPurpose: View commit history with a branch graph and short dates for easy scanning.
What do I put in [alias]?
ld = log --pretty=format:"%C(yellow)%h\\ %C(green)%ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=short --graph
Use it like this: git ld
git lg
Log/HistoryPurpose: See a colorized, graphical commit log with authors and relative times.
What do I put in [alias]?
lg = log --color --graph --abbrev-commit --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%C(bold blue)<%an>%Creset'
Use it like this: git lg
git ll
Log/HistoryPurpose: View a detailed commit log with stats and committer information.
What do I put in [alias]?
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
Use it like this: git ll
git ls
Log/HistoryPurpose: View commit log with relative dates for a quick activity overview.
What do I put in [alias]?
ls = log --pretty=format:"%C(green)%h\\ %C(yellow)[%ad]%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=relative
Use it like this: git ls
git mad
Cleanup | ⚠️Purpose: Harness the fury: discard all local changes and reset to the current HEAD.
What do I put in [alias]?
mad = reset --hard HEAD
Use it like this: git mad
git mm
Branch ManagementPurpose: Merge with a commit message but don't fast-forward. This preserves branch history in the commit graph, which is sometimes good if you want that for posterity.
What do I put in [alias]?
mm = merge --no-ff
Use it like this: git mm feature/branch
git recent
Branch ManagementPurpose: List your 20 most recently updated local branches for easy reference.
What do I put in [alias]?
recent = for-each-ref --sort=-committerdate --count=20 --format='%(refname:short)' refs/heads/
Use it like this: git recent
git st
InspectionPurpose: See a compact status with branch info for a quick overview of changes.
What do I put in [alias]?
st = status --short --branch
Use it like this: git st
git sw
Branch ManagementPurpose: Create and switch to a new branch in one go.
What do I put in [alias]?
sw = switch -c
Use it like this: git sw feature/new-design
git sync
Branch ManagementPurpose: Quickly update a local branch with its remote counterpart without checking it out.
What do I put in [alias]?
sync = "!git fetch origin $1:$1"
Use it like this: git sync branch-name
git undo
Commit Management | ⚠️Purpose: Undo the last commit while keeping your changes staged and ready for a new commit.
What do I put in [alias]?
undo = reset --soft HEAD^
Use it like this: git undo
git unstage
StagingPurpose: Remove files from the staging area without discarding your changes.
What do I put in [alias]?
unstage = reset HEAD --
Use it like this: git unstage file.txt or git unstage . for all files.
git wip
Commit ManagementPurpose: Save a quick "Work In Progress" commit to temporarily save your changes.
What do I put in [alias]?
wip = !git add -A && git commit -m "WIP"
Use it like this: git wip

Grab the whole alias snippet.
[alias]
aa = add --all
big-mad = reset --hard HEAD^
br = branch -r
bv = branch -vv
ca = commit --amend
ci = commit -a -v
cm = commit -a --amend -C HEAD
co = checkout
cp = cherry-pick
dm = !sh -c 'echo; git diff --name-status --diff-filter=ADM origin/main...$(git rev-parse --abbrev-ref HEAD) | sed -e "s/^A/\\x1b[32mA\\x1b[0m/" -e "s/^M/\\x1b[33mM\\x1b[0m/" -e "s/^D/\\x1b[31mD\\x1b[0m/"; echo; echo -e "\\x1b[94mPaths changed: $(git diff --name-status --diff-filter=ADM origin/main...$(git rev-parse --abbrev-ref HEAD) | wc -l)\\x1b[0m"'
force-safe = push --force-with-lease
graph = log --oneline --graph --decorate --all
last = log -1 HEAD --stat
ld = log --pretty=format:"%C(yellow)%h\\ %C(green)%ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=short --graph
lg = log --color --graph --abbrev-commit --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%C(bold blue)<%an>%Creset'
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
ls = log --pretty=format:"%C(green)%h\\ %C(yellow)[%ad]%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=relative
mad = reset --hard HEAD
mm = merge --no-ff
recent = for-each-ref --sort=-committerdate --count=20 --format='%(refname:short)' refs/heads/
st = status --short --branch
sw = switch -c
sync = !git fetch origin $1:$1
undo = reset --soft HEAD^
unstage = reset HEAD --
wip = !git add -A && git commit -m "WIP"
Good luck with Git. Learn more, and learn excellently, here. As always, I am wishing you a kinder sea.
(Metaphorically and literally; a kind sea was crucial for the Lun-class Ekranoplan, a 280,000kg vehicle that could only fly a maximum of 10ft above the water's surface due to its short wingspan, so could not be mobilised if seas were even mildly choppy.)
🕶 🖤