Sunday, March 31, 2013

Git in action - basic workflow

     The popularity of Git has been rocketing up for a long while. It is quite an interesting distributed version control system and there is a lot of information about Git scattered all over the Internet. However, I decided to publish a git-driven workflow.
Let's assume that we use HTTPS to connect with our remote repository. Firstly, we have to define our email address and username. It can be achieved by means of the commands:

git config --global user.name dreamuser
git config --global user.email dreamuser@dream.com

I think that specifying auto-end-line-conversion can be quite a good idea (CR LF -> LF before commit and LF -> CR LF after update) when our remote repository is hosted on Linux and we work on Windows:

git config --global core.autocrlf true

It is worth mentioning that there are three levels of configuration in Git:
--system (options defined in /etc/gitconfig [Linux] or git_installation_folder/etc/gitconfig [Windows]) - affects all of the users;
--global (options defined in ~/.gitconfig [Linux] or ) - affects currently logged user;
-by default (options defined in .git/config in current repository folder) - affects local repository;
Each level overrides options defined in the ancestor.

Now, we are ready for cloning remote repository:

git clone https://github.com/myrepo/git-test.git

By default our cloned remote repository is called 'origin'. We can enlist our remote repositories with:

git remote

and our local and remote branches with:

git branch --all

Now we have two branches (assuming that there was only one remote branch):
- master branch (local branch),
- origin/master branch (local copy of remote branch).
Both of the branches point on the same commit. It is crucial to understand that particular branch is just a pointer to the commit.

Let's say that we want to implement a new feature. We can create a new local branch (cool-feature):

git branch cool-feature

Next, we should switch to that branch:

git checkout cool-feature

We can check the position of HEAD (a pointer to the current branch) with:

git branch

HEAD is marked with asterisk (*). After that we can add a new file:

CoolFeature.java

With

git status

we can see all of the changes within our branch. What is more, we can use:

git diff --stat

to see the differences between modified files and staging area. Staging area (sometimes called 'index') is the place where we put all of the changes that will go with next commit. Our changes must be staged in order to be committed (we can also use: commit -a to auto-add all of the updates to staging area and then commit them - the shortcut does not work for the files which are not tracked).

git add *

Now, we can see the difference between staging area and committed state:

git diff --staged --stat

We can also remove our file from staging area, but we do not do it now:
git reset -- CoolFeature.java HEAD

Then, it is commit time:

git commit -m "Col feature added"

We have just made a typo in the commit description. But it is not a big deal. We can fix it:

git commit --amend -m "Cool feature added"

We can enlist the commit history with:

git log

or

git log --graph --format=oneline

Our cool-feature local branch is created and it has some changes. Now it is time to push our changes with newly created branch:

git push --set-upstream origin cool-feature

Our colleagues are able to clone the repository and work with cool-feature branch:

clone ...

The command:

git remote show origin

presents all of the remote origin branches, local branches and references (tracking). Our colleagues have to create a local branch cool-feature which will track remote branch origin/cool-feature:

git checkout --track -b cool-feature origin/cool-feature (-b allows to create a branch on-the-fly)

HEAD pointer is set to cool-feature branch. Our colleagues want to push something to cool-feature branch:

git commit -a -m "Cool feature implemented"
git push

Now, we want to check if our colleagues committed something:

git fetch
git diff --stat cool-feature origin/cool-feature
git merge origin/cool-feature

or simply:
git pull

In the meantime, someone pushed some code to the mainline (origin/master). We want to have our cool-feature branch fresh. Let's merge master->cool-feature.

git checkout master
git pull
git checkout cool-feature
git merge master

We can commit some more stuff to cool-feature. Now, we have all of the functionality implemented and we want to merge cool-feature -> master:

git checkout master
git merge cool-feature
git push

The graphical representation of the state:


We can delete our cool-feature branch both remotely and locally. It is no longer needed:

git push origin --delete cool-feature (delete remote branch)
git remote prune origin (delete all stale remote-tracking branches)
git branch -d cool-feature (delete local branch)

The state is now much more cleaner:


I think that basic usage of git is not very hard.

No comments :

Post a Comment