Git tutorial

Introduction

Git is a distributed version control system. It can be used by anyone (programmers, non-programmers) to manage their text files. E.g Homework, blogs, configuration files, source code, xml files etc.

1. Initialize

Go to your current project directory and run following command to initialize git.

$ git init

Once you have initialized a git repository you can use it to mange your files/projects. If you work in a team you can even host it yourself on a server or upload it to popular websites like github or bitbucket. For standalone use using it from a standalone directory is just fine. Some of the commands like push, pull makes more sense for a remote repository.

2. Add current changes to be versioned

Add in git adds the snapshot of changes. E.g text to be added, deleted etc. Run git add whenever some files needs to be tracked/versioned.

$ git add .

It recursively adds all the changes to be included in the next commit.

3. Committing a change

Once you have added a file, next thing you would do is commit the changes. Only after committing git can track the changes for future management.

$ git commit
$ git commit -m "Message about what you did on this version"

With the first command a detailed message can be typed. First line is use for the message title. Commit messages should be logical to the work done during current round of work, not names of what files you have committed. Work small, commit often. Always use descriptive, clear comments.

4. Knowing the status

Often you will want to know the status of your changes (are all files versioned, is there something I don’t want to be included, do I need to run commit to save the changes, or add the files first etc). You know the status of git by running following command.

$ git status

5. Branching and merging

This is one of the the most important feature and a change of tradition from traditional version control system. Your work starts to shine, once you start branching and merging. Think of it like “knowing by doing”. Code can be written in a branch and committed to the repository without effecting anybody else’s code. Once you are sure the code works, merge it to a branch where everybody else is pushing their merged code and the new changes will be added to the entire project.

A good strategy for creating a branch would be to break the work into small modules and each person handles the complete module without effecting anyone else’s module. This strategy will help the project maintain least merge conflicts. If two person edit same file and commit they are bound to have merge conflicts. If your team have too many merge conflicts, then it is best to delegate that part of work to pair programming rather than treating it as a separate unit of work.

Most popular use of branches is to work on separate features and such branches are called feature branch. Feature branches can be merged to a custom develop branch if additional merge test needs to be done and can finally merged to the master branch. The master branch can then be released to usability testing (and eventually to the client).

workflow

Fig : Typical git workflow with branching and merging.

a. Creating a branch
$ git branch feature/branchname
E.g
$ git branch feature/addtheintro

b. List branches
$ git branch -a  # lists local as well as remote
$ git branch     # lists local branches
feature/branchname
* master
feature/addtheintro

As noted by the * master branch is the currently used branch.

c. Switch branches
$ git checkout feature/branchname

In that branch do your work, test the project and if you are sure it works, commit it, switch back to master and merge it. Once you are sure your changes do not break any new changes added by others (since you created the branch), push the code to the remote repository where everyone is committing their changes. If someone else is maintaining the master branch once you push your local branch your work is done.

$ git add file6
$ git commit -m "Corrected the nasty error about the buffer overflow"
$ git checkout master
$ git merge errorcorrection
$ git branch -d errorcorrection

If the feature branch is no longer needed, it can be safely deleted as seen in the last command above. Deleting a branch is like declaring that the responsibility of that branch is done. In git no piece of committed code is lost (unless you force few nasty commands). If a deleted branch needs to be revisited, they can be checked out and worked with.

d. Get back your deleted branch

If you later found out, you needed to test something in that deleted branch, you will have to first find out hash key for that branch. In our case it is easy to identify, because of the message we used above in errorcorrection branch while commiting. To find out our commit history, we use “git log”.

$ git log
commit a2b28af2035c3f6ba4c0c15a8a2344975960890d
// Author, Date
Corrected the nasty error about the buffer overflow

We can also use “git reflog” to find out reference log compared to HEAD.

$ git reflog
a2b28af HEAD@{0}: merge errorcorrection: Fast-forward
//

Only 7 characters of the key is useful to us from first command (b2b28af). To checkout and switch to the branch you can use either of following two commands.

$ git checkout -b my-error-branch HEAD@{0}
$ git checkout -b mybranch a2b28af

6. Resolving conflicts

This is common while working with multiple people on a single project. In our case, on a single computer, it is rare, but there is nothing wrong to be prepared for that.

Lets say, you edited same file in multiple branches with same set of changes and tried to merge them all to master, and get something like this.

$ git merge testbuffer
Auto-merging file6
CONFLICT (add/add): Merge conflict in file6
Automatic merge failed; fix conflicts and then commit the result.

And the conflicting file looks like this

<<<<<<< HEAD
Hi this is error correction
This is cool
=======
Hi
>>>>>>> testbuffer

You need to fix the error in this file and remove the <<< HEAD, === and >>> testbuffer marker and add the changes again and commit.

$ git add file6
$ git commit -m "Fixed"
[master cebcc0a] Fixed

 

7. Collaboration (Setting up repository)

You should use repository, even if it seems almost unnecessary because of things we have already done without using a repository. Working on repository is a good skill to have.

Create a directory where you want to setup a repository. Setup one repository per project. Don’t put everything inside a single repository. E.g you could have separate repositories each for you blog, homework, configuration etc. Lets say, we created a directory called “blogrepo.git” for our blog (You don’t have to use .git suffix, but it is good to indicate it is a git repository). Go inside that directory and initialize a git repository using following command.

$ git init --bare

Only thing you need to remember after creating a repository is, how to get to it. Lets say, you setup blogrepo.git in your home directory, then your url would be “~/blogrepo.git”. You just need a perfect URL to get to your repository, be it local or remote. In this case we will use local URL of directory.

After doing these two things (creating a repository, remembering the URL) go back to your project directory and run following commands to make it aware of this new repository and sync with the remote branch.

$ git remote add origin ~/blogrepo.git
$ git push -u origin master
//
Branch master set up to track remote branch master from origin.

All of these three commands were one time only commands. From now on you only have to type “git push” to push the changes (after you commit your project).


8. Stashing

Stash is a place in your local work area where you can put temporary changes without committing. After you stash the changes your current branch reverts back to the last commit in the branch. What does this mean? It means that the branch will be in a state as if you had no code written in the branch. How is this useful? Git does not allow one to switch branches unless you have a clean or committed branch. After stashing your work, you can switch to some other branch and help others. You can come back to your branch and bring the work from stash back and continue your work.

You can pull others code and put the stash over that so that you can continue your work over latest changes in that branch. This feature is also called rebasing. It is one of the very common work flow.

Alert: If you like you can even use stash to completely delete your changes (if you think it does not work at all). However, it is the worst piece of advice I am giving. You should fix the error, rather than developing a habit of deleting your work. If you delete a stash it cannot be brought back and your work will be lost forever. Here are few commands you need to use stash

$ git stash # puts all changes for current branch (current version) to stash
$ git stash --help # see what other commands are available in stash
$ git stash list # list the stash
$ git stash drop # drops the top stash

9. Rebase

Moving the base (your current working repository version) to new version and stacking your work over that. Why re-basing (moving your changes over all other commits) might be useful ? If you don’t do that your commit will show all other changes along your changes. It becomes a nightmare to the person who is trying to review your piece of code. When you revisit the commit, you want to see what changes you made rather than changes made by others.

This style of workflow is one of the choices you and your team have to make. You can commit changes without rebasing, but from my experience (and after failing multiple times in the start when working with a large team), I strongly feel commits have to rebased in a project with mid (less than 10) size team.

Let me explain the workflow.

  1. You make changes (add some code, comments etc).
  2. You commit the changes.
  3. You push the changes.
  4. You get an error message saying that you have to pull the code, because you are behind current top branch
  5. Instead of using ‘git pull’ you use ‘git pull –rebase’
  6. You test your local changes, so that the pull did not break any of your code, or your code did not break the committed code.
  7. If there were some errors, you fix it, commit the changes and eventually push the changes.

Another variation to this might be once you make the local changes, ‘stash’ the changes, ‘git pull’ other’s changes, ‘stash pop’ your local changes back to your working area, test the merged and your code and after it works push the changes.

10. Miscellaneous Commands

$ git push -u origin feature/some-feature  # commit branch name to remote
$ git fetch -vp // fetch remote changes. v=verbose, p=remove broken references
$ git branch -D feature/some-feature # Delete a feature branch
$ git push origin --delete feature/some-feature # Update deleted branch to remote

Conclusion

I hope this tutorial has given you enough recipe to start working with git. As I said earlier, you don’t have to be a programmer to use git. It can and should be used to efficiently manage all text files. I hope I haven’t missed any essential commands for everyday git usage.

Cheers!!

Leave a comment

Filed under Uncategorized

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s