Monthly Archives: May 2013

Tips for working with git

This article describes basic steps regarding to working with git and also gives several tips, which can be useful and are not usually covered in tutorials.

Typical workflow

To start working with git you can create own repo with git init or you can clone an existing repository, for example:

git clone git@github.com:droolsjbpm/jbpm.git

It’s recommended to prefer SSH url, because HTTPS connection is less reliable.

You can make changes to your project and add them to next commit. And then commit the changes. You should always write a brief description of your commit.

git add --all
git commit -m "Refactored module X to work with Y."

After making necessary commits you can share your changes with other by pushing them to the server. Usually the remote on the server is called origin or upstream. The convention is that main repo of the project for all people is usually called upstream and personal forked repo on Github is called origin. I think it is a good habit to also specify a branch you want to push. For example:

git push origin master

It is good idea to regularly check for changes from the others to work with current code and prevent conflicts. The first one just downloads the changes. The second one adds the changes of others to your master branch and puts your commits on the top as the latest ones. This principle keeps linear history and is called rebasing.

git fetch upstream
git rebase upstream/master

You may easily end with unwanted changes in the repository and there seem to be no steps to revert the state back. In this cases reset can help, but it clears your changes and makes your repository the same as remote.

git reset --hard

Getting information about your repository

Here are several useful commands to get more information about your repository. So to check status of your repository, list all branches or remotes:

git status
git branch -a
git remote -v

Sometimes it is necessary to check commit history of your project.  Log is the basic command, but much better is to install tool called tig. It allows you to inspect history in command line interface in more comfortable way than simple log.

git log
tig

Interested in who screwed something up? You can check who changed which lines in selected file.

git blame README.md

Working with branches

Branches are powerful feature of Git. Instead of Subversion, the branches are cheap and simple to use. To create a new branch “MyBranch” and start working with it, just type:

git checkout -b MyBranch

This will create new branch by copying the current branch and automatically the MyBranch is switched. To change branch, for example to work again with master:

git checkout master

You can create topic branches, make changes, push them to your origin and in Github web interface make pull requests to upstream. Sometimes there are changes done in the upstream during the work on a pull request. Then you cannot simply push, because when you rebase updates from master to your topic branch, the commit IDs will change. You can use a force push here:

git checkout MyTopicBranch
git rebase master
git push --force origin MyTopicBranch

However after you are done, you may need to delete old branches. The first one deletes remotely, the second one locally.

git push origin :MyTopicBranch
git branch -D MyTopicBranch

How to rebase a Github pull request to your project

Imagine the situation. Your project is hosted on Github. Somebody forks your repository and creates a pull request to your repo. Github offers you a green button “Merge pull request” if there are no conflicts to automatically merge the changes of a contributor to your repository. This will add the changes to your upstream but will create an additional merge commit. Better approach can be the git rebase operation, which has some significant advantages over merge. The main reason is clean and linear history of the commits. I do not know why, but Github does not have a button “Rebase pull request”. So to utilize advantages of rebase approach the following git command can simplify your life (taken from blog of Stuart Douglas):

git pull --rebase upstream pull/$no/head
git push upstream master

Where the upstream is the name of the Github remote where the pull request was created and $no is the identification number of the pull request. This way you can rebase the changes to your local working repository, check them, make corrections if needed, run unit tests and then push back to your upstream/origin on the server. Pushing to repository also automatically closes the pull request.

Creating a patch file

One of the simplest approaches is to commit your changes, create a patch file (for example for your co-workers) and reset hard to a previous commit:

git format-patch -M -1
git reset --hard previous_commit_id

Applying a patch

Later if we want to apply a patch file to our repository the steps are following:

git apply patch_file_name.patch