Practice Exploring the past

Last updated: January 4, 2023

Getting an overview of history

As a list

git log lists all past commits in a pager (so scroll down with Space and quit with q ).

Go back to git_lesson and try it out:

cd /path/to/git_lesson
git log

Of course, our history is very short, so our history tree is very simple. For long histories, this is a powerful way to get an overview of the full history.

As a list with one line per commit

For a compact version with a single line per commit, you can run:

git log --oneline

Getting fancy

By playing with the various flags of git log , you can customize the commit log to your liking: different colors make it easier to read and you can get information about commit author or time while keeping it compact.

To find out about all the available options of git log , run man git-log .

Try for instance:

git log \
    --graph \
    --date-order \
    --date=short \
    --pretty=format:'%C(cyan)%h %C(blue)%ar %C(auto)%d'`
                   `'%C(yellow)%s%+b %C(magenta)%ae'

As a graph

The --graph flag allows to view this history in the form of a graph.

git log --graph

This may not seem very useful with our simple history because it is linear with a single branch (a single version of history). But in complex situations with several branches, this can be really useful.

Exploring past commits

git log is great to view the whole history. But maybe you want to explore one particular commit in more detail.

Checking out a commit

In order to explore a commit, you "check" it "out". This replaces the current content of your working tree with the content of the working tree at that commit. In other words, it allows you to travel back in time to the state of your project at that commit.

To do so, you need the hash of the commit of interest. You can copy it from the output of git log . For example, if the commit of interest has the hash e7447c2 , you would run:

git checkout e7447c2

Note: Git prevents you from checking out a commit if this would result in the loss of information: if the commit you want to checkout conflicts with any uncommitted changes, you will first need to commit or stash them. Stashing changes means to put them aside for the time being, so that they aren't in the way: changes are moved out of the working tree and into a "stash", from which they can later be retrieved.

Once you have checked a commit out, you can look at the files.

The concept of HEAD

When looking at the output of git log , you may have noticed this: (HEAD -> master) and wondered what this was all about.

HEAD is a file in the .git directory of your project. You should go to that directory and look for it.

It is a pointer to the current branch. In our case, we only have one branch since we never created any additional branch. By defaut, that branch is called master .

(HEAD -> master) means that we are on the branch master . In other words, HEAD is pointing at the branch master .

If you run git log again now, you will see that HEAD is not pointing at master anymore. It is pointing directly at the commit we checked out. We are now in a "detached HEAD state".

Going back to "the present"

To return to the latest commit, you need to "reattach HEAD" and have it point again at the branch master .

This is done by ckecking out master :

git checkout master

Showing changes between versions

git diff shows changes between any two elements (between commits, between a commit and your working tree, between branches, etc.).

Examples:

Difference between the working tree and the index (i.e. all your unstaged changes on tracked files):

git diff

Difference between the index and your last commit (i.e. your staged changes). Note that this is what you would be committing if you ran git commit :

git diff --cached

Difference between the working tree and your last commit (so both of the above):

git diff HEAD

Difference between the last commit and the commit before that:

git diff HEAD~ HEAD

Difference between 2 commits of hash <hash1> and <hash2> :

git diff <hash2> <hash1>

Difference between the tips of 2 branches (both commands are equivalent):

git diff <branch2> <branch1> git diff <branch2>..<branch1>

Difference between the tip of <branch1> and the state of <branch1> when <branch2> was started from it:

git diff <branch2>…<branch1>

Comments & questions