Contents
Git allows us to define aliases, which are basically our own commands we can use. They may be just a calls for other commands with parameters, or even shell scripts. Possibilities are unlimited.
Do you ever google for this Git command you forgot every time? Often execute several commands one by one, every time in the same combination for a final effect? Or saw a really nice Git command on the internet, but with way too more flags to use it in a real-life? Git aliases are the solution.
Here I will show Git aliases that I use in everyday work. With
- Speed up everyday work with handy Git aliases
- Simpler Git branch first push with no more errors
- Git fast-forward merge – why you should turn it off
Defining first Git alias
Aliases are part of the Git configuration that is saved to the ~/.gitconfig
file. They can be added or modified directly by editing this file, or by executing a
Let’s create an alias git status
git s
command – simple abbreviation.
git config --global alias.s status
Alternatively, we can ~/.gitconfig
[alias]
s = status
In both cases, we add new alias named s
for status
command. Since then those two calls are equal.
git status
git s
In ~/.gitconfig
file more aliases may be added to the [alias]
block, we don’t need to repeat it. We just add next lines under it.
Here I will show all examples in a form of file lines. You don’t repeat [alias]
block name, but I will put them in every snippet just to be clear on to which group we should add it.
Useful Git aliases for everybody
Handy shortcuts for Git commands
[alias]
s = status
c = commit
go = checkout
gob = checkout -b
d = diff
dc = diff --cached
It may look silly at first. Oh, we can save 5 letters calling git status
.
But when you start to use those short command versions, you will find it frustrating to go back. Those versions are two times shorter (git
git status
git commit
$ git s
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
$ git gob feature-1
Switched to a new branch 'feature-1'
$ echo "some changes" >> README.md
$ git s
On branch feature-1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git a
On branch feature-1
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
$ git c -m 'Update README'
[feature-1 2b9345f] Update README
1 file changed, 1 insertion(+)
Alias I use to move between the branches, git go
, has a new alternative available from Git 2.23. It’s git switch
, which is dedicated to changing branches. But still, I prefer my shorter version.
Beautiful and meaningful Git history log
[pretty]
better-oneline = "format:%C(auto)%h%d %s %Cblue[%cn]"
[alias]
tree = log --pretty=better-oneline --all --graph
ls = log --pretty=better-oneline
ll = log --pretty=better-oneline --numstat
details = "!f() { git ll "$1"^.."$1"; }; f"
For those we need to declare a new git log
format first, so we can use it in all three aliases.
The first 3 aliases (lines #5-7) are used to show Git history in a nicer form. git tree
is my favorite one and most used, as it shows a branching graph similar to the one shown on GitHub or GitLab. Irreplaceable in a branch-based workflow.
You can think about git ls
git ll
ls
The custom format we define makes the output of all 3 commands nice and significant. We get short commit hash, message, author, and branch name pointing on that
Last one, git details
(line #9), is used to show the same statistics git ll
git details HEAD
This last alias has a different syntax than all previous. It starts with an exclamation mark (!
), which makes Git execute it as a shell command rather than git
command. The commands will be always executed in a root repository directory. Additionally, we need to wrap it in a function to be safe using positional arguments – see explanation here.
$ git ls
1a45b2d (HEAD -> master) Merge branch 'feature-1' into master [Maciej Radzikowski]
2fe9377 (feature-1) Update README [Maciej Radzikowski]
b5cc426 change [Maciej Radzikowski]
22653f3 first commit [Maciej Radzikowski]
$ git tree
* 1a45b2d (HEAD -> master) Merge branch 'feature-1' into master [Maciej Radzikowski]
|\
| * 2fe9377 (feature-1) Update README [Maciej Radzikowski]
|/
* b5cc426 change [Maciej Radzikowski]
* 22653f3 first commit [Maciej Radzikowski]
Plurals for listing all elements
[alias]
branches = branch -a
tags = tag
Those two aliases are very helpful, especially for beginners. They make listing all branches and tags easy with just a plural form of the word. Additionally, it fixes
Fast files adding and committing
[alias]
a = !cd ${GIT_PREFIX:-.} && git add . && git s
aa = !git add -A && git s
ac = !cd ${GIT_PREFIX:-.} && git add . && git c
aac = !git add -A && git c
Those commands will speed up committing but needs to be used with care.
git a
will add files from our current directory and subdirectories to the index/staging area, ready to be committed. It will also show git status
right away, so you will see what is the state of your repository after the call. Remember to check if no random files were added automatically with this command by a mistake.
git aa
will do a very similar thing but will add all modified files from the repository, no matter from what directory you will call it. You can memorize these two commands as “add” and “add all”.
The other two aliases are extended versions of previous ones. They will additionally commit changes. Using them is very helpful and time-saving, but we need to be sure only what we want is committed.
$ git s
On branch feature-2
nothing to commit, working tree clean
$ echo "new change" >> README.md
$ git ac -m 'Update README'
[feature-2 4e28b6b] Update README
1 file changed, 1 insertion(+)
$ git s
On branch feature-2
nothing to commit, working tree clean
Clearing Git workspace and index
[alias]
unstage = reset HEAD
cleanout = !git clean -df && git checkout -- .
The first aliasunstage
git aa
The next alias behaves differently. It acts on the files in the workspace (not added to the staging area git add
git cleanout
will undo all changes from the files in the workspace and remove all new, never committed files. Effectively we will get a clean repository state of the last commit.
Carefully, both discard
and cleanout
will cause you loos uncommitted changes!
$ git s
On branch feature-3
nothing to commit, working tree clean
$ echo "some change" >> README.md
$ touch new-file-1
$ git a
On branch feature-3
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
new file: new-file-1
$ git unstage
Unstaged changes after reset:
M README.md
$ git s
On branch feature-3
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
new-file-1
no changes added to commit (use "git add" and/or "git commit -a")
$ git cleanout
Removing new-file-1
$ git s
On branch feature-3
nothing to commit, working tree clean
Undoing commits and merges
[alias]
uncommit = reset --soft HEAD~1
unmerge = reset --hard ORIG_HEAD
How many times did you realize that you committed or merged branches too soon? Here are commands to revert it easily. They do exactly what the names suggest.
git uncommit
will remove the git commit --amend
when we need to make some bigger modifications or wait longer before committing.
The other alias does a similar thing for branch merges. When we git merge
git unmerge
unmerge
ORIG_HEAD
Both these commands rewrite Git history by removing commits. A good practice is not to do such operations on commits already pushed to the remote repository. In fact, without special permissions to the remote repository, we won’t be even able to push such changes. Therefore it’s best to use uncommit
unmerge
Showing Git merge details
[alias]
merge-span = "!f() { echo $(git log -1 $2 --merges --pretty=format:%P | cut -d' ' -f1)$1$(git log -1 $2 --merges --pretty=format:%P | cut -d' ' -f2); }; f"
merge-log = "!git ls `git merge-span .. $1`"
merge-diff = "!git diff `git merge-span ... $1`"
Git branch merges may cause a lot of headache, especially for beginners. Here is a way to at least understand and review what was introduced by a given merge.
merge-span
merge-log
merge-diff
$ git gob feature-4
Switched to a new branch 'feature-4'
$ echo "first change" >> README.md
$ git ac -m 'Edited README'
[feature-4 c6fca5d] Edited README
1 file changed, 2 insertions(+)
$ echo "second change" >> README.md
$ git ac -m 'Edited README again'
[feature-4 5a09b0d] Edited README again
1 file changed, 1 insertion(+)
$ git go master
Switched to branch 'master'
$ git merge feature-4
Merge made by the 'recursive' strategy.
README.md | 2 ++
1 file changed, 2 insertions(+)
$ git merge-log
5a09b0d (feature-4) Edited README again [Maciej Radzikowski]
c6fca5d Edited README [Maciej Radzikowski]
Summary
Having aliases for most common actions and using them will speed up and simplify everyday work, allowing us to get most from the version control system.
There is nothing stopping you from adding more aliases. You can create them by yourself based on your most common actions. There are also plenty of other ready to use aliases created by various people. I’ve also taken some of my aliases from them and got inspired by others. Here they are:
- https://github.com/GitAlias/gitalias
- https://gist.github.com/robmiller/6018582
- https://gggritso.com/human-git-aliases
If you have your own favorite aliases, share them in the comments. If I find something useful for most programmers, I will add it to the snippets in the article.
you have many much interesting articles.
Do you know that you can speed up everyday work with Scrum?