Git : Branching – I

There are situations where more than one feature is being added to the same repository at the same time. In those cases, branching can be useful.

Branching is a feature by which git maintains two versions of the same repository in parallel , with different histories if needed .

What is a branch ?

In git , a branch is just another symbolic reference to a commit. We saw in the previous article that git maintains the changes as commits , trees and blobs. So let us assume that our repository consists of seven commits in the branch master. The branch master points to the latest commit. From this point, we saw that a particular commit can be used to reconstruct the entire history of the repository , by retracing by its parent attribute.

Consider this index

* 90b68fc (HEAD -> master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

We can see there are 3 branches , master , new_branch , new_2 . All the branches are linked to a commit. There is also a special branch/reference called HEAD which points to the current version that you are in.

There is a similar concept called tags , which is very similar to a branch.

Tags vs Branches

Branches as we saw is a reference to a commit . Similarly tags also is a reference to a commit in the work tree.

Whenever we commit something while in a branch, the branch is updated and it moves to the new commit. Consider the tree in the previous example.. Let us add a commit commit10 to the tree while in the master branch and let us see what happens to the tree.

trials/Git$ git log --oneline --graph --all --decorate
* 90b68fc (HEAD -> master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit
trials/Git$ git checkout master
Already on 'master'
trials/Git$ touch anotherfile
trials/Git$ git add .
trials/Git$ git commit -m "commit10"
[master 807cee1] commit10
 2 files changed, 1 insertion(+)
 create mode 100644 anotherfile
 create mode 160000 new_repo
trials/Git$ git log --oneline --graph --all --decorate
* 807cee1 (HEAD -> master) commit10
* 90b68fc added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

As we can see the current branch master moved to commit10 as we commit it in the tree. Lets try the same with a tag.

We have created a tag with in the actual master branch before the commit 10 as version_master.

So the tree now looks like this..

* 807cee1 (HEAD -> master) commit10
* 90b68fc (tag: version_master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

Let us checkout to the tag and try the same thing that we did with a branch .

trials/Git$ git checkout version_master
warning: unable to rmdir new_repo: Directory not empty
Note: checking out 'version_master'.

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 

HEAD is now at 90b68fc... added thank
trials/Git$ git branch
* (HEAD detached at version_master)
  master
  new_2
  new_branch
trials/Git$ touch added_tag_file
trials/Git$ git add added_tag_file
trials/Git$ git commit -m "commit to a tag"
[detached HEAD ee978d1] commit to a tag
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 added_tag_file
trials/Git$ git log --oneline --decorate --graph --all
* ee978d1 (HEAD) commit to a tag
| * 807cee1 (master) commit10
|/
* 90b68fc (tag: version_master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

As soon as we checkout to a tag, git warns us that we are now in a no-branch land ! When we try to see what branch we are in , we are shown that, the current branch is HEAD detached at version_master. This clearly shows something is not normal. When we go on to commit something we see that the tag remains at the same place , unlike a branch , and our HEAD has moved to a different commit.

As we have learnt from here, Branch is a dynamic reference to a commit , whereas a tag is a static reference to a commit.

Branches move on .. Tags dont !!

Lightweight ?

Git Branches are extremely lightweight unlike other version control systems. It is just a symbolic reference to a commit and nothing more. The information about a branch is available in .git/refs/
folder

For the above tree, These are the contents of the folder

trials/Git$ ls .git/refs/heads
master  new_2  new_branch

If we read the contents of the file, this is what we find..

trials/Git$ cat .git/refs/heads/master
90b68fc5f860b9fe6fc628a8e7c48e63aa0389e4
trials/Git$ cat .git/refs/heads/new_2
1d61006a01b7438f73ccb92b8704bdbb0b0f40bc
trials/Git$ cat .git/refs/heads/new_branch
9060af7eb68b76d47f9dccf6b2a77e9fa7e6ea0d

As we can see, the contents of a branch is just the SHA id of the commit that it is pointing to and nothing more.

Creation

git branch as the name implies that it has got something to do with branches. Using git branch displays all the current branches .

git branch -l creates branches from a commit mentioned.

trials/Git$ git log --oneline --decorate --graph --all
* ee978d1 (HEAD) commit to a tag
| * 807cee1 (master) commit10
|/
* 90b68fc (tag: version_master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit
trials/Git$ git branch -l masterv2 ee978d1
trials/Git$ git log --oneline --decorate --graph --all
* ee978d1 (HEAD, masterv2) commit to a tag
| * 807cee1 (master) commit10
|/
* 90b68fc (tag: version_master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

Creation of tag is similar

trials/Git$ git tag grand_parent 2b9e414
trials/Git$ git log --oneline --decorate --graph --all
* ee978d1 (HEAD, masterv2) commit to a tag
| * 807cee1 (master) commit10
|/
* 90b68fc (tag: version_master) added thank
| * 9060af7 (new_branch) added abc
| * 82c5aa6 added xyz
| * 5088a37 commit8
| * 2337e97 commit7
| * cb435f4 commit6
| * cf2aca1 commit5
| | * 1d61006 (new_2) stashed commits
| |/
|/|
* | 871d5ee commit9
|/
* 2b9e414 (tag: grand_parent) Adding gitignore
* dab6699 Adding change2
* f8a10f7 Adding change1
* 00a5cfe Initial commit

Moving Ahead

We have seen what branches are for . And a little about creation of tags and branches etc. We will look into more intriguing portions of Branching in the next article.

1 thought on “Git : Branching – I”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s