Git Version Control – Fundamentals (Part 3)

To recap, a Git commit allow us save a snapshot of our project at a specific point in time. The snapshot makes it possible to retrieve the state of the project at a later time.

Git starts to get interesting when you’re collaborating with other developers on a shared repository. First, you need to be aware of a concept called Branching. While commits allow us to save snapshots of our repository, a branch is a pointer to a commit. This pointer moves with each new commit and maintains a reference to the most recent commit.

To illustrate, checkout the diagram below:

Git already creates a default master branch on initialisation. Because we have added 2 commits, master now points to the most recent one. As the Master branch is merely a pointer, we can create another pointer to the current recent commit. This process is called branching. It is executed with the command git branch <branch_name>. Go ahead and try it:

$ git branch dummy

What i’ve done is create a branch called dummy that points to the current master branch state. So in essence, what we have now is this:

We can list out all the local branches in our repository. Running command git branch, you should see something like this:

$ git branch

* master

The program logs the two branches to the console: master and dummy. The asterisk sign (*) beside master indicates you’re currently editing the copy of the project on the master branch. All changes and commits we make, will only reflect on the master branch and not the dummy branch you created earlier.

The HEAD Pointer

Before I continue, i will talk about another pointer called the HEAD pointer. The HEAD pointer always points to the current branch. So at the moment, HEAD points to the master branch. You can confirm with this command:

$ cat .git/HEAD

ref: refs/heads/master

If you switch your current working branch from master to dummy, the command cat .git/HEAD will give a different output.

Switching Branches

What we did earlier with the git branch dummy was to create a new dummy branch referencing the current commit of our master branch. Any change we make at this point will not reflect on the dummy branch. In order to make changes on the dummy branch, what we do is switch to dummy. To do that, we use the git checkout command.

$ git checkout dummy

Switched to branch 'dummy'

We get a log output indicating we’re now on the dummy branch. Try running git branch command.

$ git branch

* dummy

Our loving asterisk is now on the dummy branch. So that means changes and commits will reflect on dummy and not master. This is what we have now:

Now let’s add a few commits on the dummy branch. Assume we have some new requirements that involve creating a new file called index.txt.

$ echo 'This is our index file' > index.txt

If you run git status, you should see the log output showing the untracked file. Next, we stage and commit this new change. To do that:

$ git add .
$ git commit -m "Created index file"

[dummy a871487] Created index file
 1 file changed, 1 insertion(+)
 create mode 100644 index.txt

Our project now looks like this:

Say we have another requirement that involves creating two new files, readme.txt and random.txt.

$ echo 'read me content' > readme.txt
$ echo 'random string' > random.txt
$ git add .
$ git commit -m "Created other files"

[dummy 6ca054d] Created other files
 2 files changed, 2 insertions(+)
 create mode 100644 random.txt
 create mode 100644 readme.txt

Now, we have advanced dummy branch by 2 commits ahead of master. Our project now looks like this:

If we switch back to the master branch, we won’t see any of the new changes we have on the dummy branch. Let’s try that.

$ git checkout master

Switched to branch 'master'

We’re now on the master branch. If you view your directory contents, you shouldn’t see files we created on the dummy branch. We can checkout a new branch from master called dummy-2.

$ git checkout -b dummy-2

Switched to a new branch 'dummy-2'

$ git branch

* dummy-2

The command: git checkout -b <branch_name> allows us create a new branch and check it out in one command. It’s a shortcut for git branch <branch_name> and git checkout <branch_name>. Our project now looks like this:

If we made any new changes and commits, the dummy-2 branch will be advanced ahead of master similar to how we advanced the dummy branch.

$ echo 'More Updates' >> hello.txt
$ git commit -am "Added more updates to hello.txt" 

[dummy-2 8fa1be2] Added more updates to hello.txt
 1 file changed, 1 insertion(+)

The branches dummy and dummy-2 have divergent changes from parent hash 8e7c655. Both branches have exclusive commits not contained in the other branches. In the next post, i’ll dive into how to incorporate changes from one branch into another using techniques called Merging and Rebasing.