GIT STRATEGY, A PRACTICAL SAMPLE – PART II

GIT STRATEGY, A PRACTICAL SAMPLE – PART II

Git Tutorial Part II

ARCHITECTURE RESPONSIBILITY

In the previous part of this article, we saw an architecture separation to support modular development. However, there are still more pending topics to talk about:

Who maintains the common architectural part? And in which branch?

The answer to the first question is that someone must be in charge of the architecture, it can be one of us, it can be Bryan, but one person must be responsible for it. You may not believe it, but I have seen huge projects in big companies, where this responsibility was spread among many people and the motive was unclear. This results in poor quality and redundant work.

Also note that experience, high technical skills, and long-term vision are a must for this task.

Because the architecture is independent of the modules and can be the responsibility of a different team, we can create a new branch for it. It’s the same process as when we created the bikes branch, so I won’t repeat that process here.

BRANCH PER TASK

Some days ago, Steve sent us the requirements for the v2.0, so we are now left with a lot of work in progress, in both modules.

Just at this moment, an important bug in the production version was detected. One way to manage this situation, and because branching in git is really fast and cheap, is to create a branch-per-task strategy for bug fixing.

Let’s see how that is done:

git checkout master
git branch fix_0001
git checkout fix_0001

This goes to the master branch, creates the fix_0001 branch and go to fix_0001 branch.

Edit the incorrect file (i.e. bikes.html):

<html lang=”en-US”>
  <head><tittle>Bike part store</tittle></head>
  <body>Some work</body>
</html>

Commit it:

git commit -a -m “Fixed bug 0001, changed tittle for bikes”

After testing it, merge the hot-fix branch to the master branch (note that –no-ff is used to avoid a fast-forward merge and make the examples more clear).

git checkout master
git merge --no-ff fix_0001

This is the state after these commands are executed:

git branch per task example

In this case, we solved only one bug in fix_0001, but you should note that it is not necessary to have a pure branch-per-task strategy. We can group several bugs for one release and make a common branch for all of them.

We can also have a specific branch alive for bug-fixing, where bugs are resolved and from time to time we update the fixes to the master branch and generate a release. But in this case, it is not a good idea to work directly on it, because partially resolved bugs can interfere with “ready-to-release” bugs and block the merges, it’s better to manage this situation with an integration branch.

Okay now that we have taken care of the bug, let’s see what Steve needs next.

INTEGRATION BRANCH

Steve call us again, the important bug is fixed but he is still upset and wants to make sure that in the future an independent team will test the releases.

Bryan and I have almost finished the version 2.0, so we need to mix the work and generate a release for the test team. We are going to create an integration branch:

git checkout master
git branch integration_v2

We can now merge the v2 work from the modules to the integration branch:

git checkout integration_v2
git merge --no-ff bikes
git merge –no-ff scooters

The first command goes to the integration_v2 branch, the second merge is to the bikes branch and the third merge is to the scooters branch.

This is the actual state:

git integration branch example

Now we can generate the releases for the test team from the code in the integration branch (integration_v2).

The question that we should ask ourselves now is that what kind of conflicts can arise while using this strategy?

Well, there are two types of possible conflicts that can occur:

Type 1: Occurs when the same file is changed from a common ancestor in the master path and in one module path. An example of this case would be a file that was modified in the commit fee8ca (bug 0001) and also in the commit 55b5a (work done on the bikes branch).

Type 2: Occurs when the same file is changed from a common ancestor in the module paths.

An example of this case would be a file that was modified in 55b5a (work done on the bikes branch) and also in 1fa8ee (work done on the scooters branch).

These conflicts must be resolved in the two previous mergers, when we merge the modules work into the integration branch. The type2 can occur only in the second merge.

MERGE BEFORE INTEGRATION STRATEGY

One variant to avoid conflicts in these merges over the integration branch is that first, update the module branches from the master branch, and later do the merges to the integration branch. This option also has the benefit that leaves the module branches updated with the master content.

First, update the bikes branch from the master (orange merge in the graph):

git checkout bikes
git merge master

In this merge, only type 1 conflicts can occur.

Secondly, update the scooters branch from the master (orange merge in the graph):

git checkout scooters
git merge master

In this merge, only type 1 conflicts can occur.
And then, as before, merge into the integration branch:

git checkout integration_v2
git merge bikes
git merge scooters

The first command goes to integration_v2 branch, the second merge to the bikes branch and the third merge is for the scooters branch. In the bikes merge, no conflicts can occur, and in the second only type 2 conflicts can occur.

This is the state after all these commands:

git merge before update an integration branch

Doing it this way has the benefit that each team resolves their type 1 conflicts in their own branch, so when we do the merge over to the integration branch, only type 2 conflicts can occur.

If the architecture is well designed, type 2 conflicts should be unusual, as the modules don’t usually touch common code.

RELEASE A NEW VERSION

The last step, just after the test team approved the version, is to merge it to master for production release.

git checkout master
git merge –no-ff integration_v2

That results in this state:

git release from an integration branch

At this point, we can tag the master with V2 version and generate a release from the master branch.

The project will continue, as Steve will continue contacting us and Bryan, so the master, bike, and scooter branches will remain alive, and this process will be repeated over and over again, for successive versions.

Don’t forget that at this point, to update the bikes branch and the scooters branch, some bug fixing was done in the integration branch. This can be done from the master branch after the v2 release was tagged.

This is only one example of how we can manage a complex project with a repository strategy, but of course, it is not the only one, and even in some cases probably not the best.

You will need to figure out how each case works, and what makes sense to implement, so the important thing here is to understand the basics.

I hope this example helps you to improve your knowledge of the basic repository techniques.

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: