Git aliases for fun and profit

12 min read Ekranoplan, by Uamee
"Git gets easier once you grasp the basic idea that branches are homeomorphic endofunctors, mapping submanifolds of a Hilbert space." - Anonymous
The interior of the lun-class Ekranoplan. Dials upon dials on turquoise metal, very complicated.
[The interior of the Lun-class Ekranoplan.]

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

Staging

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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

Review

Purpose: 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/History

Purpose: 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/History

Purpose: 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/History

Purpose: 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/History

Purpose: 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/History

Purpose: 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/History

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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

Inspection

Purpose: 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 Management

Purpose: 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 Management

Purpose: 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

Staging

Purpose: 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 Management

Purpose: 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


A picture of the Lun Class Ekranoplan, abandoned on the Dagestan shore.
[Abandoned off of the Dagestan coast; too weird to live. Too rare to die.]

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.)

🕶 🖤