Git is as db let’s query some commits

Henrique Mota
5 min readMay 24, 2018

--

After the success that my first post achieved, I decided to write this post to help my readers understand even more the concepts behind git. If you didn’t read my first post you can click in the next link:

In the previous article I showed how git how git works under the hood. In this post I will interactively travel in a git graph, just to show you how sometimes we put restrictions to ourselves without realising the simplicity and freedom that git provide us.

Let’s get our hand dirty

Initialising our git project:

> mkdir git-time-travel
> cd git-time-travel
> git init
Initialized empty Git repository in /Users/bullian/git-time-travel/.git/

Creating 1 file:

> echo "line 1" > file.txt

Checking the status of our project:

> git statusOn branch masterNo commits yetUntracked files:
(use "git add <file>..." to include in what will be committed)
file.txtnothing added to commit but untracked files present (use "git add" to track)

We can see that we are on the branch master, no commits done until now and our file is untracked by git at this moment, the same is to say that git doesn’t have any version of this file yet in his repository.

To commit a file we have to explicitly add it to the staging area. Some users that had changed from svn to git may think that this step is unnecessary, but the reality is that it puts you on a position where you control everything that is versioned in your project.

We are going to add and commit the file we just created, then we are going to commit 4 more versions adding 1 more line to the file for each commit.

> git add file.txt
> git commit -m "Add first line"
> echo "line 2" >> file.txt
> add file.txt
> git commit -m "Add second line"
> echo "line 3" >> file.txt
> add file.txt
> git commit -m "Add third line"
> echo "line 4" >> file.txt
> add file.txt
> git commit -m "Add fourth line"
> echo "line 5" >> file.txt
> add file.txt
> git commit -m "Add fifth line"

We end up with a graph like this:

Reading a commit with git checkout

In the last article I highlighted the fact that the git repository is a database. Like every database you can perform a read operation without side effects. Say I want to see how the file was in the third commit (fd3f55a):

> git checkout fd3f55aNote: checking out 'fd3f55a'.You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>HEAD is now at fd3f55a Add third line

Like the feedback indicates, every change you make here will not impact any branch. Let’s look at the content of the file:

> cat file.txtline 1
line 2
line 3

And finally let’s look how the git graph is right now:

The only thing that changed here was the HEAD reference, that now is pointing to the third commit. If you execute git log, you will only see the first 3 commits, if you want to see all the commit execute git log — all.

Just for fun, let’s perform an hard reset, and then checkout master to see if it changes anything:

> git reset --hard HEAD~1
> git checkout master
> git log --pretty --graph
* 2047343 - (HEAD -> master) Add fifth line (18 minutes ago) <bullian>
* 0eb8dca - Add fourth line (18 minutes ago) <bullian>
* fd3f55a - Add third line (19 minutes ago) <bullian>
* f7a6649 - Add second line (20 minutes ago) <bullian>
* 25b346f - Add first line (20 minutes ago) <bullian>

Not even an hard reset over a detached HEAD impacts a branch.

Once you achieve a state you can recover it

Let’s use now the git reset hard on a branch and pretend that after the git reset we realised that we made a big poo.

Do you have something to worry about?

Absolutely nothing.

Let’s see:

> git checkout master
> git reset --hard HEAD~3 #reset master to 3 commits before

The graph now will look like this:

Oh my god what a big pile of 💩, it was a mistake I just wanted to visit this node. Nothing to worry about we just need to make a git reset back to the right commit. But you don’t have always access to this git graph and your project may be so big that you cannot realise what was the previous commit your branch was pointing to.

What can we do?

Use reflog is the answer. It lists each command you made and references the commit the branch was referencing after the execution. In our situation we want the command before the reset so:

> git reflogf7a6649 (HEAD -> master) HEAD@{0}: reset: moving to HEAD~3
2047343 HEAD@{1}: checkout: moving from f7a66499ba191d86a6c5e5e1a8542ff9e221e02b to master
> git reset --hard HEAD@{1}> git log --pretty --graph* 2047343 (HEAD -> master) Add fifth line
* 0eb8dca Add fourth line
* fd3f55a Add third line
* f7a6649 Add second line
* 25b346f Add first line
(END)

We have our branch back.

I hope you enjoyed

Kind regards

Henrique Mota

--

--