As with any developer, who got into programming between 1995 - 2005, I have been using CVS and Subversion as my primary source code repository for most of the time - both as part of work and also to manage my personal development projects.
However, couple of years back, during my involvement with open source projects like PHP as part of Web Stack development for Open Solaris and Linux, I got introduced to distribution version control management system like Mercurial. The concepts of distributed version control intrigued me and the benefits of such a system became immediately apparent. I guess, I fell in love with Mercurial almost instantly. However, in recent times, I am getting more inclined towards 'Git' - yet another distributed source code management system - mainly because of its Swiss Army knife approach and also thanks to the popularity of sites like 'Github' - which allows developers to collaborate in a more simpler fashion.
Ok, coming back to the topic of my today's blog - At work, our project still uses 'CVS' extensively - which typically hosts the main repository in a central system. This kind of centralized system can block your work if your team is geographically dispersed and you end up frequently waiting for your code to be reviewed and approved before you are allowed to commit your patch.
After working with distributed system and enjoying its benefits like the one mentioned here , here and here, I decided to mirror our CVS based project within Git and here are some of the tips and tricks that I have learned while using Git. Hope this helps some one, who is trying to learn and use Git at work..
1. Installing Git
Git installation experience can vary depending on what OS you are using for your development. I use RHEL4 (RedHat Enterprise Linux 4) for my development and I had to install the following rpm git-184.108.40.206-1.el4.rf , git-arch-220.127.116.11-1.el4.rf to install 'Git' on my system. I guess, a simple googling can provide you instructions on how to install Git on your system.
2. Creating a repository.
Creating a repository within 'Git' can be as simple as moving to the top level of your source code directory and running 'git init'. Some times, you might be pulling repository from your friend's workspace. In that case, you will need to run
git clone <location of your friend's git workspace location>. This location can be accessible either through 'http://' or 'ssh://'
3. Making changes and committing to the repository
Any time, you make changes within your source repository, you will need to explicitly tell 'Git' to add this change within its repository. For me, coming from CVS or Subversion (svn) back ground, this was a big adjustment. In Git, I typically run a command like
git ls-files --modified -> This command lists out the list of files that you have modified.
Now, to add these modified files, I run a command like below
git ls-files --modified | xargs git add -> This command will add the modified files within Git repository.
Also, Git allows you to show the status of what is going to be committed etc. You could get this information by running a command like:
git status -s | less
Alternatively, if you want to add all the files that has changed , you could run 'git add --all' . This option allows you to capture all the files without having to manually add these files to the 'Git staging' area as I mentioned earlier.
4. Saving your workspace
Git has a concept called 'staging' -> which allows you to stage all your changes and later decide if you want to commit this change within the repository. For example, any time, you make a change to your source file and run 'git add <filename>' , git marks this change within 'staged' mode. At this point, if you are comfortable with committing this change, you could proceed to run 'git commit' or simply save these changes by running 'git stash <some-change-name>'. This allows you to save your changes without committing and also getting back to it at a later point of time.
5. Managing Branches
As I mentioned earlier, Git allows you to maintain multiple branches within your workspace. For example, if I am working on 2 bugs at a same time, I could do some thing like
-> make change to foo.c
-> git add foo.c
-> git commit -m "initial changes"
-> Now, I can fork 'foo.c' by creating a branch and working on a crazy change. To do this, I could do something like
-> git branch <crazy-changes>
-> Now, to checkout this branch, I typically do some thing like 'git checkout <crazy-changes>'.
-> Now, I can make a real crazy change within 'foo.c' and commit this change within this branch by doing some thing like
git add foo.c
git commit -m "crazy changes."
-> Finally, I could switch back to the old/main branch, by doing some thing like
git checkout master
-> From this (the main) workspace, I have options to take a look at all the crazy things that I have done by doing some thing like
git diff master..crazy_changes
-> and apply this crazy changes within my current workspace by doing some thing like:
git merge crazy_changes
git ls-files --modified | xargs git add
git status -s -> this tells me if I missed adding any files. If yes, I need to manually add those files.
-> Finally, I can commit this crazy changes within the main branch by doing some thing like
git commit -m "merging crazy changes within the main branch."
5. Bringing in changes from 'main' branch:
-> Let us say, you are working on your 'crazy changes' branch and you know that your main branch has additional features that you want to bring within your 'crazy changes' branch. You will need to run the following command:
git rebase master -> This will cause Git to bring in changes from your 'master' branch and then apply your changes on top of it.
6. Collaborating with multiple programmers:
Frequently, I need to test my changes on various platforms (like Linux, Solaris, Windows etc.). In these cases, I typically try to replicate my workspace on these platforms by running a command like:
git clone ssh://htaccess/home/sriramn/projects
Now, I can work on my repository in my remote machine and make changes there. When I am done with those changes, I can publish those changes by running the following command:
git pull origin/master -> bring in latest changes from the origin/master branch
git add <file> -> capture the changes made in my local repository.
git commit -m "changes in remote machine."
git push origin/master -> publish my local changes to the original repository.
For any of the commands that I have mentioned here, you can also run 'git help <command-name>' to get more help.