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
- Distributed Version Control
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.
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>
<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 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
option with various optional flags. The following is the basic
$ 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
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
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,
be used with
$ 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.
$ git remote add <NAME OF UPSTREAM> <URL OF UPSTREAM>
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
<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).
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
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>
<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
master branch. So, first you have to switch to
switching branches, refer to Branch section. Then to perform actual
merge, run the following command.
$ git merge test
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.
$ git merge <REMOTE NAME>/<BRANCH NAME>
Disclaimer: This wiki page is by no means a full description of all of the features of Git.
- Git Website: git-scm.com
- Pro Git by Scott Chacon and Ben Straub: Pro Git
- Tech Talk: Linus Torvald on Git: youtube.com
- Introduction to Git with Scott Chacon of GitHub: youtube.com
- Wikipedia page of Git: wikipedia.org