Skip to main content

Harshal V. LADHE

Git Aliases Worth Adding to Your ~/.gitconfig

Tested Git aliases for history, undo, fixups, and search.
Read the full post: Advanced Git: Rebasing, Internals, and Real-World Workflows
Published at:
Last updated:
Estimated reading time:4 min read
Terminal-styled illustration of a ~/.gitconfig alias block with short Git commands expanding into their full versions.(opens full-size image in a new tab)
Aliases grouped by task, beside a graph log and a one-step fixup.

Introduction

Git's built-in commands are powerful but verbose — nobody wants to type log --graph --format='%C(auto)%h%d %s' twenty times a day. Aliases let you name the incantations you use most, and because they live in ~/.gitconfig, they follow you to every repository.

This snippet is a curated, tested set of aliases for everyday work: reading history, undoing mistakes, fixing up earlier commits, and finding things.

The Aliases

Paste this into ~/.gitconfig. If you already have an [alias] section, that's fine — Git merges them.

[alias]
  st = status --short --branch
  lg = log --graph --format='%C(auto)%h%d %s %C(dim)— %an, %ar%C(reset)'
  lga = lg --all
  last = log -1 HEAD --stat
  staged = diff --cached
  wdiff = diff --word-diff=color
  unstage = restore --staged --
  discard = restore --
  undo = reset --soft HEAD~1
  amend = commit --amend --no-edit
  fixup = "!f() { target=$(git rev-parse --verify \"$1^{commit}\") || return; base=$(git rev-parse --quiet --verify \"$target~1\") || base=--root; git commit --fixup=\"$target\" && GIT_SEQUENCE_EDITOR=: git rebase --interactive --autosquash --autostash $base; }; f"
  wip = "!git add --all && git commit --quiet --no-verify -m WIP"
  unwip = "!git log -1 --format=%s | grep -qx WIP && git reset --quiet HEAD~1"
  pushf = push --force-with-lease --force-if-includes
  recent = for-each-ref --sort=-committerdate --count=15 --format='%(committerdate:relative)%09%(refname:short)' refs/heads/
  find = log --all --oneline -S
  who = shortlog --summary --numbered --email --no-merges HEAD
  ignored = ls-files --others --ignored --exclude-standard
  root = rev-parse --show-toplevel
  aliases = "!git config --get-regexp '^alias\\.' | sed 's/^alias\\.//'"

Prefer to keep them in their own file? Save the block as ~/.gitconfig.aliases and include it from ~/.gitconfig:

[include]
  path = ~/.gitconfig.aliases

Either way, run git aliases afterwards — if the list prints, everything loaded.

What Each One Does

Reading history and status

  • git st — compact status with the branch and ahead/behind counts on the first line.
  • git lg / git lga — one-line coloured graph of the current branch, or of every branch.
  • git last — the latest commit with a per-file summary of what changed.
  • git staged — what's about to be committed (the diff git diff alone won't show you).
  • git wdiff — word-level diff, far easier to read for prose and Markdown.

Undoing things

  • git unstage <file> — take a file out of the staging area, keeping your edits.
  • git discard <file> — throw away unstaged edits to a file. Irreversible.
  • git undo — remove the last commit but keep its changes staged, ready to recommit.
  • git amend — fold staged changes into the last commit without reopening the editor.

Editing earlier commits

  • git fixup <commit> — commit what's staged as a fix to <commit> and immediately autosquash it in, no editor involved. Works on the very first commit too. If the rebase stops on a conflict, resolve it and run git rebase --continue, or back out with git rebase --abort. For several fixes at once, the third-party git absorb picks the target commits for you.
  • git wip / git unwip — park everything (including untracked files) in a throwaway WIP commit, then unpack it again. unwip does nothing unless the last commit is literally WIP, so it can't eat a real commit.
  • git pushf — the safe force-push: refuses if the remote has commits you haven't fetched and integrated. Reach for it after fixup or amend rewrites a commit you'd already pushed.

Finding things

  • git recent — your 15 most recently touched branches, newest first.
  • git find <text> — every commit, on any branch, that added or removed <text>.
  • git who — contributors ranked by commit count.
  • git ignored — files Git is ignoring, handy when a .gitignore rule catches too much.
  • git root — the repository's top-level directory, e.g. cd "$(git root)".
  • git aliases — list everything above, so you never have to open the config to remember.

Adding Them From the Command Line

Prefer not to edit the file by hand? Simple aliases can be set with git config:

git config --global alias.st 'status --short --branch'
git config --global alias.undo 'reset --soft HEAD~1'
git config --global alias.pushf 'push --force-with-lease --force-if-includes'

Shell aliases (the ones starting with !) are possible this way too, but their nested quoting gets awkward on the command line — paste those into the file instead.

Notes & Tips

  • ! means shell. An alias starting with ! runs as a shell command instead of a Git subcommand, which is how fixup, wip, and aliases chain several commands together. Shell aliases always run from the repository root.
  • The f() { …; }; f pattern wraps a shell alias in a function so arguments like $1 land exactly where you want them.
  • Aliases can call aliases. lga is just lg --all.
  • Built-ins win. You can't alias over a real command — alias.log is silently ignored.
  • Version notes. restore needs Git 2.23+ and --force-if-includes needs Git 2.30+.
  • Bigger jobs deserve a script. Once an alias needs options, safety checks, or error messages, promote it to a git-<name> executable like git fix-dates, git prune-branches, or git sync.

Key Takeaway

A handful of well-chosen aliases removes most of Git's day-to-day typing — and because each one is just a named Git command, they stay easy to read, tweak, and share.

Changelog

  • — Added cross-reference to snippet '`git sync`: Update Your Branch from `main` in One Command'
  • — Added cross-reference to snippet '`git prune-branches`: Delete Merged and Squash-Merged Branches'
  • — Initial publication.
This snippet is licensed under CC BY 4.0 by the author.

Share this snippet

Spotted a mistake or something outdated in this snippet? Suggest a correction.

  • git fix-dates: Fix GitHub Commit Dates After a Rebase

    Reset committer dates to author dates, then safely force-push.
    A git fix-dates command that resets committer dates to author dates after a rebase or amend, keeps merges intact, and force-pushes safely.
    Published at:
  • git sync: Update Your Branch from main in One Command

    Fetch, fast-forward main, and rebase your branch onto it.
    A `git sync` command that fetches, fast-forwards `main` without a checkout, and rebases or merges your branch onto it — with autostash and undo.
    Published at:
  • git prune-branches: Delete Merged and Squash-Merged Branches

    Delete merged, squash-merged and rebased local Git branches safely.
    A git prune-branches command that deletes local branches merged into main — including GitHub squash merges git branch --merged misses — with a restore command for each.
    Published at: