Git Alias: Custom Commands for Faster Workflows – The Only Guide You'll Need
Git alias tutorial: stop typing long commands.
20+ years shipping production infrastructure and CI/CD at scale. Written from production experience, not tutorials.
- ✓Basic Git knowledge (init, commit, push, pull)
- ✓Access to a terminal or command line
- ✓A Git repository to practice with
Create a Git alias with git config --global alias.. For example, git config --global alias.lg 'log --oneline --graph --all --decorate' lets you run git lg instead of that long log command. Use --global for all repos or omit it for just the current repo.
Think of Git aliases like speed dial on your phone. Instead of dialing a full 10-digit number every time, you press one button. Git aliases let you map a short word to a long, complex Git command. You still get the full power of Git, but you type way less. It's like having a personal assistant who knows your most-used commands and executes them with a single word.
| Chrome | Firefox | Safari | Edge |
|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ |
You know that moment when you're in the middle of a hotfix, your boss is breathing down your neck, and you have to type git log --oneline --graph --all --decorate for the fifth time? That's time you don't have. Git aliases are the duct tape that holds my workflow together. They turn 40-character commands into 4-character ones. And no, they're not just for lazy people — they're for people who value their time.
Here's the problem Git aliases solve: Git commands are verbose. Some are downright painful to type repeatedly. git commit --amend --no-edit? That's 30 keystrokes for something you might do 20 times a day. Aliases cut that down to git amend (or even git ca if you're feeling spicy). They also reduce typos — fewer keystrokes means fewer chances to fat-finger a flag and mess up your repo.
By the end of this article, you'll be able to create your own Git aliases, use advanced tricks like shell commands and external scripts, and avoid the common pitfalls that have burned me (and many others) in production. You'll never type git log --oneline --graph --all --decorate again. I promise.
Why You Need Git Aliases (And Why You've Been Wasting Time)
Every time you type a long Git command, you're wasting mental energy and risking typos. I've seen developers type git commit -m "fix: typo" a hundred times a day. That's fine. But when you need git log --oneline --graph --all --decorate --since="2 weeks ago" --author="John", you're going to mess it up. Aliases let you bundle that into git mylog. The payoff is immediate: less typing, fewer errors, faster workflow.
But aliases aren't just about saving keystrokes. They're about creating a personal vocabulary for your Git workflow. You can chain commands, run shell scripts, and even integrate with external tools. In a team, shared aliases can enforce conventions — like a git wip that stages everything and commits with a standard message. The key is to start small and build up.
--global for aliases you want in every repo. Use --local (or omit) for project-specific aliases. I keep a set of global aliases for common operations and repo-specific ones for custom workflows.Creating Your First Alias: The Anatomy of a Git Alias
A Git alias is just a config entry. The syntax is git config [--global] alias.<name> '<command>'. The command can be any Git command (without the git prefix) or a shell command prefixed with !. Let's break it down.
First, decide the scope: --global for your user (all repos), --system for all users on the machine (rare), or no flag for just the current repo. Then pick a short name — I use st for status, co for checkout, ci for commit (old SVN habit). The value is the command string in quotes.
Important: If your command has arguments (like --oneline), include them in the alias. The alias replaces the entire command, so git lg becomes git log --oneline --graph --all --decorate. You can also append additional arguments when you run the alias — they get appended to the end of the command.
! for simple Git commands — it's slower because it spawns a shell. Only use ! when you need shell features like pipes, loops, or arguments. For simple aliases, just use the Git command without !.Advanced Aliases: Shell Commands and External Scripts
When a simple Git command isn't enough, you can prefix the alias value with ! to run a shell command. This opens up infinite possibilities: pipes, loops, conditionals, even calling external scripts. But with great power comes great responsibility — and potential disaster.
For example, I have an alias git wip that stages all changes and commits with a timestamp: !git add -A && git commit -m "WIP $(date)". Another one: git cleanup that deletes merged local branches (but be careful — see the production incident above).
You can also point an alias to an external script. Just use !path/to/script.sh. The script runs in the repo root. This is useful for complex multi-step workflows that you want to version-control with your project.
git pushf defined as !git push --force-with-lease origin $(git rev-parse --abbrev-ref HEAD). One wrong branch and you've rewritten history. Always add a safety check or use --force-with-lease at minimum.Managing and Sharing Aliases: The Git Config File
All your aliases live in your Git config file. Global aliases are in ~/.gitconfig (or ~/.config/git/config). Local aliases are in .git/config of the repo. You can edit these files directly — sometimes faster than using git config commands.
To list all aliases: git config --global --get-regexp alias. Or open the file and look under the [alias] section. To remove an alias: git config --global --unset alias.<name>.
Sharing aliases with your team? Put them in a script that everyone sources, or use a .gitconfig file in the repo that you include via git config --local include.path ../.gitconfig. But be careful — local config can override global, and you don't want to force aliases on teammates who might not want them.
~/.gitconfig manually, make sure there's no trailing whitespace or missing newlines. Git's parser is picky. One stray space can break all your aliases. I've spent 30 minutes debugging why git st suddenly stopped working — turned out I had a tab instead of a space.Alias Gotchas: What Can Go Wrong and How to Fix It
Aliases seem simple, but they have sharp edges. Here are the ones that have bitten me and my teams.
1. Argument handling: If your alias is !f() { git log -$1 HEAD; }; f, and you run git last, it passes no argument, so $1 is empty, and the command becomes git log - HEAD — which errors. Always provide a default: !f() { git log -${1:-10} HEAD; }; f.
2. Quoting: If your command contains spaces or special characters, wrap the whole value in single quotes. Inside, use double quotes if needed. For example: git config --global alias.wip '!git add -A && git commit -m "WIP"'. The outer single quotes protect the inner double quotes.
3. Shell expansion: When using !, the command runs in a shell. Variables like $HOME get expanded. If you want a literal $, escape it with \$. This is especially tricky in aliases that use $(...) for command substitution.
4. Performance: Each ! alias spawns a new shell. For simple commands, avoid !. For complex ones, the overhead is negligible.
! aliases in a CI/CD pipeline, the shell environment might be different (e.g., no $HOME set, or a different shell). Always test your aliases in the exact environment where they'll run. I've seen git deploy fail on Jenkins because the script assumed Bash but the default was Dash.When Not to Use Aliases: The Overkill Trap
Aliases are great, but they're not always the right tool. Here's when you should skip them.
1. One-off commands: If you only run a command once a month, don't alias it. You'll forget the alias name and waste time looking it up. Just type the full command or use shell history (Ctrl+R).
2. Complex workflows that need branching logic: If your alias has multiple conditions, loops, or interactive prompts, put it in a proper script. Aliases with complex shell functions become unreadable and hard to debug. Use a script and alias to that script.
3. Team-wide enforcement: Don't force aliases on your team via .gitconfig includes unless everyone agrees. Some developers prefer their own aliases or none at all. Instead, document recommended commands in a README or provide a script that sets up optional aliases.
4. Commands that change behavior based on context: If an alias needs to behave differently depending on the branch or repo, a script is better. Aliases are static — they always run the same command.
~/.git-aliases.sh script that defines all my aliases via git config commands. When I set up a new machine, I just run that script. It's also version-controlled in my dotfiles repo. That way I never lose my aliases.The Alias That Deleted Our Staging Branch
git cleanup and the staging branch disappeared. The team spent 2 hours recovering from a remote backup.cleanup was defined as !git branch --merged | grep -v '\*\|main\|staging' | xargs git branch -d. It worked locally but on a shared machine, the branch list included staging because it was merged, and grep -v didn't filter it correctly (regex issue). The xargs git branch -d deleted it.!git branch --merged | grep -v -E '(\*|main|staging|production)' | xargs git branch -d. Added -E for extended regex and escaped parentheses properly. Also added a --dry-run option first.- Always test aliases with
--dry-runorechobefore running destructive commands. - And never trust
grep -vwithout testing the regex on the exact output.
git: 'xyz' is not a git command. See 'git --help'.git config --global --get alias.xyz. 2. If empty, alias wasn't created or was removed. 3. Re-create alias. 4. If alias exists but still fails, check for typos in the alias name when running.git config --global --get alias.<name>. 2. Manually run the expanded command to isolate the issue. 3. Check for shell expansion issues: if using !, test the shell command separately. 4. Verify quoting: ensure single quotes around the alias value.git config --local in the repo for CI/CD-specific aliases. 3. Define aliases in a setup script that runs before Git commands. 4. Avoid ! aliases that depend on specific shell features (e.g., Bash-specific syntax).git config --global --get alias.xyzgit config --global --list | grep aliasgit config --global alias.xyz '<command>'| File | Command / Code | Purpose |
|---|---|---|
| create-first-alias.sh | git config --global alias.st status | Why You Need Git Aliases (And Why You've Been Wasting Time) |
| alias-examples.sh | git config --global alias.lg 'log --oneline --graph --all --decorate' | Creating Your First Alias |
| advanced-aliases.sh | git config --global alias.wip '!git add -A && git commit -m "WIP $(date)"' | Advanced Aliases |
| manage-aliases.sh | git config --global --get-regexp alias | Managing and Sharing Aliases |
| alias-gotchas.sh | git config --global alias.last '!f() { git log -$1 HEAD; }; f' | Alias Gotchas |
| when-not-to-alias.sh | git config --global alias.rebaselast '!f() { GIT_SEQUENCE_EDITOR=: git rebase -i... | When Not to Use Aliases |
Key takeaways
! only when you need shell features; for simple Git commands, omit it for better performance.--dry-run or on a safe branch firstInterview Questions on This Topic
How does Git handle argument passing in aliases? What happens if you run `git lg -5` when `lg` is defined as `log --oneline --graph --all --decorate`?
git lg -5 becomes git log --oneline --graph --all --decorate -5. This works because Git's log command accepts -5 as a limit. However, if the alias uses ! with a shell function, arguments must be handled explicitly via $@ or $1.Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Written from production experience, not tutorials.
That's Git. Mark it forged?
4 min read · try the examples if you haven't