I have been using git for a number of years now and have accumulated some awesome git aliases. In this blog post I want to share some of my favourite git log
aliases. The log command is probably my most used command, it lets me view the latest changes, compare changes between branches, view just fetches changes and examine changes other team members made.
For those of you that don’t know, Git is a free and open-source distributed version control system. The git log
command is used to display code changes in chronological order.
Basic Log Commands
Running the usual git log
will give you a list of all commits in chronological
order. Use the usual vi bindings –gg, G, Ctrl-D, Ctrl-U– to navigate swiftly
around the log.
git log
commit b9326fa37b261dcfa92827e32ad1b0739b1a1005
Merge: a022731 ba40fbd
Author: Author1 <author1@hotmail.com>
Date: Wed Jun 3 20:15:03 2015 +0100
Merge pull request #1501 from ...
Did something ...
commit ba40fbd68c1e7c3b497a03984b912f01431d7d58
Author: Author2 <author2@yandex.com>
Date: Sun May 31 19:32:52 2015 -0400
Restored some bits that were overwritten.
This looks ok but I almost never read the log in this format, it’s takes up far too much screen
with useless data. So I use the --oneline
flag to condense each commit into
one clean line.
git log --oneline
b9326fa Merge pull request #1501 from ...
ba40fbd Restored some bits that were overwritten.
a022731 Merge pull request #1505 from ...
7b17c1b type ...
This is my first alias l = git log --oneline
.
View the latest changes with the -p
flag–it stands for patch. This will
display all commits with patch information appended to the bottom of each one.
This is immensely useful for viewing the changes each commit introduced.
I use this all the time after a git pull
.
git log -p
commit 923c4ec0e1756346bee5bea48392e16156692313
Author: Ben D'Angelo <ben@bendangelo.me>
Date: Fri May 29 17:46:16 2015 -0400
Updated gems
diff --git a/Gemfile.lock b/Gemfile.lock
index 3b1def6..ec90fea 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -65,7 +65,7 @@ GEM
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
mercenary (0.3.5)
- mini_magick (4.2.4)
+ mini_magick (4.2.7)
multi_json (1.11.0)
parslet (1.5.0)
blankslate (~> 2.0)
Most people don’t know this, you can display the log of other branches by passing in a branch name or a commit hash. Remember a branch name essentially is a pointer to a hash.
git log dev
git log origin/dev
There are times when I want to view the changes a specific fix introduced but it happened maybe a week ago and is not easily accessible by scrolling. With the
--grep
flag and the issue number you can find the log.
This can even be coupled with the -p
flag to display the patch.
git log --grep=#1234 -p
commit dcd60d87741eccc0323b3de3749c6da1042ad59d
Author: Ben D'Angelo <ben@bendangelo.me>
Date: Sun May 31 13:04:44 2015 -0400
Fixes #1234 Something
...
I made the alias lgr
stands for log grep. I always prefix my log aliases with
an l to show it uses the log command.
lgr = !sh -c 'git l --grep=$1 --max-count=20' -
I have personally never used this command but am itching to try it out. It lets you see changes of a function over time–yeah not kidding. There are two version of this command. One lets you specify a line range–which works well for scripting languages– and the other a regex. I found the regex works well in C++.
git log -L :main:main.cpp
In both cases the file path has to be specified. You’ll be amazed at what you learn by stepping through a functions history.
Comparing Commits in Branches
Comparing branches is something I do on a daily basis. Did this branch get merged into master? How many commits is development ahead? Are common questions.
Say your team has been pushing commits to the dev branch for some time. You know master is quite behind dev but you don’t know by how much. So you want to log of all the commits in dev that master does not have.
Of course the easiest way is to compare the two branches.
git log dev --not master --oneline
# or
git log master..dev --oneline
923c4ec Updated gems
8afb047 Updated font sizing.
The second comparison might be confusing but it is quite simple.
git log master..dev
This means log all commits reachable by dev that are not reachable by master. You can also think of it as, ignore commits in master and display commits only in dev.
So, you now know that dev has two commits that master does not have but, master could have commits that dev does not have. What if you want to see commits that are not reachable by both dev and master? This brings us to the triple dot syntax.
git log --left-right master...dev --oneline
> 923c4ec Updated gems
> 8afb047 Updated font sizing.
< c9035a3 Hot fix
First thing you should look at is the arrow, this shows which branch the commit
belongs to. The >
is pointing to dev
and <
is pointing to master
, the
arrow direction is relative to construction of the command. Reversing the
comparison will reverse the arrows. Hence the flag name–left-right– master is
on the left, dev is on the right.
git log --left-right dev...master --oneline
< 923c4ec Updated gems
< 8afb047 Updated font sizing.
> c9035a3 Hot fix
So what does this tell you? There are two commits inside dev that master doesn’t have and there is one commit–a hotfix–inside master which dev doesn’t have. And you did this all commandline–what a time saver.
Remember you can even add the -p
flag to view the changes.
Seriously, remember these two syntaxes, I use these on a daily basis.
Moving on, the log command can even be used to preview merges. Say you been working on a feature branch for some time. You can run this command to view the commits that have to be merged in.
git log --no-merges feature12..master
You can even preview incoming commits to your branch.
git fetch
git log master..origin/master --oneline
923c4ec Added something
# looks good, merge in
git merge origin/master
A git fetch
fetches changes and puts them in the remote version of your
branch, in this case origin/master
. You can then compare the remote
branch–origin/master–
with your local branch–master.
Or view the commits that just went in from a git pull
or a git merge
.
git log ORIG_HEAD.. --oneline
923c4ec Added something
ORIG_HEAD
is the previous state of HEAD
before it was changed by a command
like git merge
or git rebase
. You might notice there is no argument on the
right side–ORIG_HEAD..– the right side will default to HEAD
.
Understanding the Graph
I’ve shown most of the log commands that I use in my daily workflow, except one–the graph flag. It gives you such a nice overview of the branches history and the state of other branches as well.
git log --graph --oneline
* b7de477 Added feature 2
* f737f26 Added feature 1
* b9326fa Merge pull request #1501
|\
| * ba40fbd Cleaned up something
| * 486bd4a Fix 1
| * 63bf944 Fix 2
| * 23b2f3b Fix 3
| * 297802f Fix 4
| * 42c303c Fix 5
| * 3817be4 Fix 6
* | a022731 Merge pull request #1505
|\ \
| * | 7b17c1b Typo
This graph tells us not only the recent commits in the branch but also nicely displays the merges that took place. Two arrows pointing to an asterisk means it was a merge commit–it brought two separate commits together through a new commit, ie b9326fa.
So how is this useful? Being able to see merge commits and the commits they
integrate allows for better decision making. For example I wouldn’t want to
interactively rebase ba40fbd
because it’ll lead to confusing conflicts, a
better approach would be to do a soft reset.
My Aliases
Here is a big list of my favourite log aliases, do to them as you wish.
This aliases improves the graph functionality by adding relative dates, name of committer and branch names.
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative --decorate
This is my default log commit, each commit is on one line and displays committer, relative date and branch names.
l = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ (%cr)\\ %Cblue\\ [%cn]" --decorate
923c4ec (HEAD, origin/dev, dev) Updated gems (5 days ago) [Ben D'Angelo]
8afb047 Updated font sizing. (6 days ago) [Ben D'Angelo]
This is a more specialized log, it displays commits on single lines and displays all file changes with stats on line removals and additions. I use this to find which file had the most work done on it.
ll = log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat
923c4ec (HEAD, origin/dev, dev) Updated gems [Ben D'Angelo]
1 1 Gemfile.lock
8afb047 Updated font sizing. [Ben D'Angelo]
1 11 _assets/stylesheets/highlight.css.sass
11 1 _assets/stylesheets/text.css
1 1 _assets/stylesheets/vendor/skeleton.scss
1 1 _config.yml
This alias has to be one of my favourites, it displays all commits on a single line and displays file changes on their own line. I use this to quickly find which files were modified to look for potential bugs or to pick up someone else’s work.
ls = log --pretty=format:\"%C(yellow)%h %Cgreen(%cr)%Creset %s %C(bold blue)[%cn]%Creset\" --name-status
923c4ec (5 days ago) Updated gems [Ben D'Angelo]
M Gemfile.lock
8afb047 (6 days ago) Updated font sizing. [Ben D'Angelo]
M _assets/stylesheets/highlight.css.sass
M _assets/stylesheets/text.css
M _assets/stylesheets/vendor/skeleton.scss
M _config.yml
This is used to see incoming commits after a git fetch
. The @{u}
is
shorthand for grabbing the upstream of the branch. It’s equal to
origin/{branch_name}
.
lf = log ..@{u} --stat
This displays all the commits added today.
lt = log --stat --since='1 Day Ago' --graph --pretty=oneline --abbrev-commit --date=relative
Thanks for reading. You can checkout all my configurations on my dotfiles repository.