Version Control System

Version Control System or VCS is very integral part of developing software these days. VCS automates the task of creating and storing versions after making new changes on the project. This is a very tedious task if done by hand, but VCS simplifies this process. Almost all of the projects right now uses VCS of one way or the other.

Types of Version Control

VCS can be broadly classifies into two major types.

Centralized Version Control

VCS following this approach generally have a central repository which is used by everyone. Also, you have to stay connected to the central repository in order to commit changes as all the changes are instantly send and updated there. This approach has many problems but some of the projects still use this type of VCS. A very common Centralized Version Control System is Subversion.

Distributed Version Control

This approach is relatively new as compared to Centralized Version Control and tries to solve a lot of problems. VCS following this approach specifically, Git, are pretty commonly used these days by the majority of the projects. Generally, when downloading the repository, it fetches all of the history and basically mirrors the upstream repository locally, so commits can be made locally without needing the connection to upstream repository. And whenever you sync the local version with upstream, it sends the changes and updates the upstream. Git is an example of Distributed Version Control System.


Git was developed by Linus Torvalds himself for maintaining Linux Kernel back in 2005, when due to the large number of developers contributing to Kernel, it was getting harder day by day to maintain the project with the then available tools. Now, Git is maintained by Junio Hamano.

There are many Git repository hosting providers available with different plans based on Public or Private repository. A few of them are as follows:

As explained above when cloning the repository from the upstream repository, it basically fetches the complete history, branches and tags. Basically everything from the upstream mirror. This makes the local version an exact mirror of the upstream, thus the word Distributed.

Note: Although Git servers generally prefer bare versions of Git repository for various reasons.

For fetching ,Git supports various protocols, detailed information of which is available here. Out of these protocals SSH is considered relatively secure.


Basic Usage

In order to make Git track changes under a folder, the first thing you need to do is initialize the Git repository. The following command can be used for the same.

$ git init

If you created a new repository on Git hosting providers, or forked an upstream project, then you need to clone the repository locally. The following command will fetch the repository.

$ git clone <URL OF REPOSITORY>

Note: <URL OF REPOSITORY> often specify the protocol by which you want Git to clone.


After making changes to an existing Git repository, you need to commit changes. Its a 2 step process, first you need to tell Git which changed files you want to commit. This can be done using add option of git.

$ git add <FILE NAME>

Note: If you want to add all the changed files, you can use a wildcard for this.

$ git add .

Second step is to actually create a commit. This can be done using the commit option with various optional flags. The following is the basic commit command.

$ git commit

This command opens an interactive text editor (generally nano), where you can type the commit message. If you want to skip this and directly insert commit message in commit command itself, the following command can be used instead.

$ git commit -m "YOUR COMMIT MESSAGE HERE"

Commit also has a feature to amend the last commit, so lets say you created a merge request, but the maintainer of the project requested changes, then updating the same commit is considered better then creating a new commit. That way maintainer or other developers can easily track changes. There are many more use cases for amending the commit. For doing this, amend option can be used.

$ git commit --amend

This commit is interactive and will open a text editor (generally nano) in which you can edit/change/update the commit message reflecting. Saving and exiting the text editor will amend the commit.

Note: After amending a commit you have to force push it on the repositories for further information about force push, refer to Push section.


After making one or more commits, you want to update the repository on Git hosting providers, to accomplish that Git has a push option. Default format of push command is as follows.

$ git push <REMOTE NAME>

Note: If there is only one remote, then <REMOTE NAME> part can be skipped. For more information on remotes, refer to the Remote section.

Sometimes you need to forcefully push to upstream, when the already pushed commit is later changed. That way upstream repository will rewrite the history with the newly pushed commit rather then the old commit. To force push, -f can be used with push command.

$ git push -f <REMOTE NAME>

A special can of push is when you push to an empty repository or pushing to a new branch on upstream, as then you also have to tell Git which branch you want to set on upstream to track the current local branch.

$ git push --set-upstream <BRANCH>

When you are working on a project collaboratively then generally there is an upstream repository of the project and then your forked versions on Git hosting providers. This is important to keep your forked version in sync with the upstream repository. To accomplish that first you need to add a new upstream remotein your local repository.


This will add the upstream repository as a remote from which you can fetch and push depending of the permissions you have. To fetch the changes on the upstream the following can be used.

$ git fetch <NAME OF UPSTREAM>

To fetch from all the remotes at once, --all flag can be used.

$ git fetch --all

Note: <NAME OF UPSTREAM> can be anything when you add it but then you have to use the same name later (There are options to change name or url later).

The fetch option will just fetch the changes and will not merge them on its own. To do that you have to use merge option, for that refer to Merge section.

To list all the remotes show option can be used.

$ git remote show

A more verbose version with url can be handy sometimes.

$ git remote -v

Branches are very handy when you work on multiple features/bugs. A use case of branches can be, when you created a merge request which is not accepted yet, but you have to work on a feature in the mean time. The convention is to keep the master branch (or the default branch) in sync with upstream and create new branches for each new feature/bug.

To create a new branch from the current branch, the following can be used.

$ git checkout -b <NEW BRANCH NAME>

To delete a branch after merging, the following can be used.

$ git branch -d <BRANCH NAME>

Note: Just deleting the branch will not automatically merge it. To actually merge, refer to Merge section.

To forcefully delete branch without merging, -D can be used instead.

$ git branch -D <BRANCH NAME>

For switching branches, just checkout option is to be used.

$ git checkout <BRANCH NAME>

Note: Here <BRANCH NAME> refers to the branch you want to switch to.


Merge is actually as easy as executing a command, much like other basic Git commands, until you have merge conflicts, then it can get a little messy. For the sake of this section I’m assuming there is no merge conflict.

To merge local branch, first switch to the branch you want to merge it into. To make is more clear I’m going to use example. So, I want to merge test branch into master branch. So, first you have to switch to master. For switching branches, refer to Branch section. Then to perform actual merge, run the following command.

$ git merge test

Note: Here test is an example, replace it with branch you want to merge.

If you are looking for updating the repository with the upstream changes, that is also done using merging but instead of using just branch name, use a prefix <REMOTE NAME>/ with the branch name. So, the resulting command will be something like this.


Disclaimer: This wiki page is by no means a full description of all of the features of Git.

See Also