In the 2nd post of the series I'll show how I extract information from a Git repository. There are three layers I will operate on:
- highlighting output to draw the attention on a particular piece of information on the screen
- formatting a log message
- searching through commit messages or through the codebase
For the purpose of this article I will use two Git repositories:
- a small personal project which has some changes in both the working directory and the staged files,
- Noir framework repository from GitHub
git status
Let’s start by putting some colours on git status
. We have to modify
~/.gitconfig
and add the following part:
[color "status"]
added = blue
changed = yellow
untracked = white ul
λ git status
Now, git status
will get some nice coloring, like on the
screen below:
Let’s remove unnecessary information from git status
by adding the --short
option. I use it pretty often so I have binded it to git s
for convenience.
λ git status --short
As shown below there is only the essential status information
git diff
Another area of improvement concerns git diff
command. As before let’s add
some colours to the output by modifing ~/.gitconig
.
[color "diff"]
meta = white bold
frag = magenta ul
old = red bold
new = green bold
Now git diff
will render an output similiar to the one below
There is a useful option called --stat
which provides a summary for each file
from git diff
. It can be used for staged files as well.
λ git diff --stat
λ git diff --cached --stat
git log
git log
shows the commit logs.
λ git log
There is a lot of information here and it takes of lot space. In the following paragraphs I'll propose some neat alternatives.
Log with Diff Stat
We can include diff
stats in the log output using --stat
option.
λ git log --stat
Log with Patch
We can also associate diff
content with each commit in the log output using
-p
option. There is also -2
which limits the output to only the last two entries
λ git log -p
λ git log -p -2
Log Format: Graph
We can apply various formats to git log
output. For example, we could display
a ASCII graph on the left thanks to --graph
option.
λ git log --graph --date=short
Log Format: Short
Let's create a more concise git log
output using the following format.
λ git log --pretty=format:'[%h] %an %cr: %s'
I have binded it to git los
alias.
Log Format: Changes
Let's add to the previous output a list of files changed for each commit. It could be done this way:
λ git log --pretty=format:'[%h] %an %cr: %s' --name-status
I have binded it to git changes
alias.
Log Format: Summary
We can go even further and adjust the previous output with a git diff
stats
that visually show how a file or files associated with each commit changed
λ git log --pretty=format:'[%h] %an %ar: %s' --stat
I have binded it to git summary
alias.
Log Format: Changelog
We can also generate a simple change log (aliased to git changelog
) by using:
λ git log --pretty=format:' * %s'
As before I have git changelog
alias for that format in my ~/.gitconfig
.
Log Format: Full Graph
Or a neat graph which is binded to git lof
in my personal config.
λ git log --graph --pretty=format:'[%h] -%d %an %cr: %s' --abbrev-commit --date=relative
Log Filtering
git log
output can be filtered in various ways.
Time Range
Time range can be specified using --since
or --before
options:
λ git log --since=2.weeks
By Author OR By Commit Message
To easily find commits authored by a specific person, I use git log
with --author
option. If I wanted to search through commit message instead, there is --grep
option.
It can be easily combined with other options, like --since
for example.
λ git log --author=Zaiste!
λ git log --grep=Merge --since=1.week
By Author AND By Commit Message
In order to find commits authored by a specific person that contain certain words in the commit message, I could use one of the following commands.
λ git log --author=Zaiste! --grep=Merge --since=1.month
λ git log --all-match --grep=Merge --author=Zaiste!
It differs from what says git help
as the first of these commands is supposed
to look for an author OR a message, but it does AND instead; as a result --all-match
is not needed.
Code Filtering
At this point, we already know how to look through commit messages, find commits authored by a specific person, etc. Let's learn how to search in the source code.
The simplest command looks like this:
λ git grep <regexp>
It searches for a specifc regex
expression in the working tree. There is a
useful option, called --function-context
which gives a « context » for the
search. Let's compare:
without --function-context
with --function-context
For a more clear git grep
output with filename heading & line numbers, I use
three additional options: --break
, --heading
and --line-number
.
To search in the current head, use the following command:
λ git grep <regex> HEAD
To search only through .md
files, in the working directory, try this:
λ git grep 'map' -- '*.md'
These options can be easily combinated. For example, to search in the HEAD
of
branch called feature
and only through .clj
, use following:
λ git grep -e 'map' next HEAD -- '*.clj'
We can also search all revisions for a specified regexp
, like so:
λ git grep <regexp> $(git rev-list --all)
Or, we can limit the search to all revisions between rev1 and rev2, like so:
λ git grep <regexp> $(git rev-list <rev1>..<rev2>)
We can combine several regexp
expressions. For example, to search working tree for lines lines matching both init AND defn:
λ git grep -e init --and -e defn
Or, to search working tree for lines that match at least one of these two
regex
expressions:
λ git grep -e init -e defn
Finally, the following command will give the names of the files that have both defn and init somewhere in them:
λ git grep -l --all-match -e defn -e init
Summary
In this article, I only scratched the surface. There is much more options for git diff
, git status
, git log
and git grep
commands. You can get more details on each of these commands via git help <command>
.
In the next post I'll show how git
can be integrated with our favorite text editor: Vim. Stay tuned!