A successful model of branches in Git

To use the Git is important, and that includes maintaining a collaborative development environment for software manageable.

Credits

This Post is a Portuguese version of the original, in English, “A successful Git branching model“, duly authorised by the author, Vincent Driessen. Thank you man!

For technical issues, Some keywords have been purposely kept in English. I tried to ensure the originality of the text, but I confess that I had to make adjustments to facilitate understanding in our language (EN). Any correction or suggestion for improvement in the translation is welcome.

Introduction

This is not a Post teaching how to use Git. If this is what you need, I suggest taking a look at Git manual. Nor is our goal to show how to do a software versioning, in this case, see Semantic Versioning.

The proposal is to manage the team collaboration in software versioning. You know when you have several programmers “stirring” in the same source code? It is important to speed up the development, but can generate huge headache (prejudice and rework) If there is a control. To prevent a developer from overwriting each other's work and ensure a progressive development and organized, minimizing conflicts and managing software versions, is that we use Git and the model of branches then.

Blank template

In this post I present the development model that I used in some of my projects (work as particular) about of 1 years ago, and that has been very successful. It's been a long time I wanted to write about it, but never found a schedule available, so far. I'm not going to discuss project details, only about strategies of branches and management of releases.

This model focuses exclusively on Git as a tool for versioning of all our source code. (By the way, If you are interested in Git, our company GitPrime provides, in real time, some amazing data analyses for optimization of software engineering)

Why git?

For a thorough discussion of the pros and cons of Git compared to systems of centralized source code controls, see the Web. There is a tremendous “war” around that. As a developer, I prefer Git in relation to all other existing tools today. Git no doubt changed the way developers think about doing a Merge or create a branch. I come from the classic world of Cvs/Subversion, where merging/branching It's something you only do once in a while and always looks a little scary (“Beware of conflicts of Merge, they bite you!”).

With Git these actions [merging/branching] are extremely simple and represent one of the major parts of our work routine, believe me. For example, in Book Csv/Subversion, branching and merging are covered for the first time only in later chapters (for advanced users), While in any book on Git, This is seen in chapter 3 (basics).

As a result of your simplicity and repetitive nature, branching and merging are no longer something to be afraid. Actually, version control tools should help makeMerge and create branch more than anything else.

No more talk, Let's go to the development model. The model that I'm going to present here is essentially nothing more than a set of processes that each team member must follow in order to reach a managed software development process.

Decentralized, but centered

The configuration of the repository that we use and that works very well with this model branching is composed of a central repository. Note that this repository is only “regarded as” Central (because Git is a DVCS [Distributed Version Control Systems], IE, There's nothing like a central repository at technical level). We will reference this repository as origin, Since this name is familiar to all Git users.

Each developer makes pulls and travel for the origin. But beyond the relationship push-pull for centralized [origin], each developer can also pick up [pull] the changes of other pairs to form sub-teams. For example, This can be useful for working with two or more developers in a new great functionality, previously sending [pushing] work in progress for the origin. In figure above, There are the sub-teams of Alice and Bob, Alice and David, and Clair and David.

Technically, This means nothing more than Alice has defined a remote Git named Bob, pointing to the repository of Bob, and vice versa.

The main branches

In the background, This model of development is quite inspired by existing models around. The central repository has two branches [branches] major with a infinite life:

  • master
  • develop

The Branch master in origin should be familiar to every user Git. Parallel to Branch master, There is another branch called develop.

We consider origin/master as the main branch where the source code of HEAD always reflects a State production-ready [ready for production].

We consider origin/develop as being the branch main where the source code of HEAD always reflects a State with the most recent changes to be delivered in the next version. Some would call that “branch of integration”. That's where the more sinister happen constructions.

When the source code in the Branch develop reach a stable point and is ready to be released [released], all changes should be merged [merged] back to the Branch master and then marked with a version number [release]. How this is done in detail, will be discussed later.

So, each time changes are incorporated [merged] back to the master, It's generated a new version [released], by definition. We seek to be quite rigorous about it, So, theoretically, We could even use a script hook Git to create and automatically send our application to production servers whenever there is a commit in master.

Auxiliary branches

Next to the branches main, master and develop, our development model uses a variety of branches to help support the simultaneous development between team members, What 1) facilitates the tracking of new features [features], 2) prepare for delivery of a new version [release] and 3) helps to quickly fix flaws in production [hotfix]. Unlike branches main, These branches has a short lifetime, now that eventually will be removed.

The different types of branches [helpers] We can use, are:

  • Feature branches
  • Release branches
  • Hotfix branches

Each of these branches has a specific purpose and is linked to strict rules, so that, branches can give rise to branch and that branches must be merged [merged] the your targets. We will see each [branches] in an instant.

Under a technical perspective, These branches are not considered “Special”. Each type of branch It is categorized by how we use them. Anyway, are just simple branches the good old Git.

Feature branches

[Features = features/functionality]

– Can branch [branch] from:
develop
– Should merge-if [Merge] again the:
develop
– The Naming Convention branch:
Anything, except master, develop, release-*, or hotfix-*

The feature branches (or sometimes called topic branches) are used to develop new features/functionality to a next or future version. To start the development of a feature, the target version in which this feature will be embedded may well be unknown at this point.

The essence of a feature branches He is while the feature is in development, but eventually will be embedded [merged] back to the develop (to add the new feature to the next release) or thrown (in the case of an unsuccessful experience).

Feature branches typically only exist in the repository develop, not in origin.

Creating a feature branches

$ git checkout -b myfeature develop
# Switched to a new branch "myfeature"

Incorporating a feature ended in the develop

Features finalized can be merged[merged] with the Branch develop to add them to next release.

$ git checkout develop
# Switched to branch ' develop '
$ git merge --in-FF myfeature
# Updating ea1b82a ... 05e9557
# (Summary of changes)
# $ git branch-d myfeature
# Deleted branch myfeature (was 05e9557).
$ git push origin develop

The flag –No-ff causes the merge [Merge] always create a new object of commit, Although the merge could be performed with a fast-forward [FF]. This prevents lost information about the history of the existence of a feature branch, grouping all commits that have been added to the feature. Compare:

In the latter case [the figure above], It is impossible to see from the Git history which of commits were implemented within a feature; you would have to manually read all log messages. Reverse a feature one piece (IE, a group of commits), It's a real headache in the last situation, While that is easily done if the flag –No-ff has been used.

Yes, This will create a few more objects of commits (empty), but the gain is much greater than the cost.

Release branches

[Release = release/delivery/version]

– Can branch [branch] from:
develop
– Should merge-if [Merge] again the:
develop and master
– The Naming Convention branch:
release-*

The Releases branches assist in the preparation of a new production release [production release]. They allow you to dot the i's of last hour. In addition, They allow small bug fixes bugs and definition of meta-data for a release (version number, build dates, etc). To do all this work in a release branch, the develop branch stay clean to receive features the next big release [version].

The key moment to create a new release branch branching of develop is when the develop is already (almost) reflecting the desired state of new release [version]. All features candidates for the release to be built should be incorporated [Merge] the develop in this moment. Already the features facing releases future should expect a next release [version].

Is exactly at the beginning of a release branch that the next release gets a version number – not before. Until that time, the develop branch reflected changes to the “next release” [next version], but it is unclear if this “next version” will eventually be 0.3 or 1.0, until the release branch is started. This decision is made at the beginning of the release branch and is performed by the rules of the project on versioning [I suggest to see about “Semantic Versioning“].

Creating a release branch

The Releases branches are created from the develop branch. For example, Let's say that the version 1.1.5 is the current production release and we have a great release coming. The State of develop are you ready for the “next version” [next release] and we decided that this would become the version 1.2 (Instead of 1.1.6 or 2.0). So, We've expanded and give release branch a name reflecting the new version number:

$ git checkout -(b) release-1.2 develop
# Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
# Files modified successfully, version bumped to 1.2.
$ git commit -the -m "Bumped version number to 1.2"
# [Release-1.2 74d9424] Bumped version number to 1.2
# 1 files changed, 1 insertions(+), 1 deletions(-)

After creating a new branch and access it, We in the version number. Here, bump-version.sh is a shell script that changes some files from the working copy to reflect the new version. (This can, of course, be a manual change – the point is that some files change.) So, is made the commit the number of modified version.

This new branch There may be there for a while, until the release be thrown definitely. During this period, bug fixes can be applied in this branch (instead of the develop branch). The addition of new and large features Here is strictly prohibited. They must be merged [merged] in develop and, Like this, wait for the next big release.

Finalizing a release branch

When the release branch are you ready to become a real version, some actions need to be carried out. First, the release branch is merged into master (Since each commit in master is a new version by definition, Remember). Then, This commit in master should be marked for easy future reference this version history. Finally, the changes made to the release branch need to be merged [merged] again to develop, so that the releases future also contain these bug fixes.

The first two steps in Git:

$ git checkout master
# Switched to branch ' master '
$ git merge --in-FF release-1.2
# Merge made by recursive.
# (Summary of changes)
$ git tag -the 1.2

The release is now completed and marked for future reference.

Note: You can also use the flags-s or-u to sign your tag cryptographically.

To keep the changes made in the release branch, We need to put them back to the develop. In Git:

$ git checkout develop
# Switched to branch ' develop '
$ git merge --in-FF release-1.2
# Merge made by recursive.
# (Summary of changes)

This step can lead to a merge conflict (probably go, Once we changed the version number). If so, fix and make the commit.

Now, that really broke up, the release branch can be removed, Since we don't need it anymore:

$ git branch -d release-1.2
# Deleted branch release-1.2 (was ff452fe).

Hotfix branches

– Can branch [branch] from:
master
– Should merge-if [Merge] again the:
develop and master
– The Naming Convention branch:
hotfix-*

The Hotfix branches are very similar to the Release branches, They also intended to prepare a new production release, Although not planned. They arise from the need to act immediately after an unwanted State of a production version [in use]. When a critical error in a production version, must be solved immediately, then a hotfix branch can be derived from the tag that marks the existing production version in Master branch.

The essence is that the work of team members (in develop branch) can continue, while another person is preparing a rapid correction of the flaw in production.

Creating the hotfix branch

The hotfix branches are created from the Master branch. For example, assuming the version 1.2 is the current production release version running and presents problems due to a serious error. Changes in the develop leave the still unstable. We can then branch a hotfix branch and begin to solve the problem:

$ git checkout -(b) hotfix-1.2.1 master
# Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
# Files modified successfully, version bumped to 1.2.1.
$ git commit -the -m "Bumped version number to 1.2.1"
# [hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
# 1 files changed, 1 insertions(+), 1 deletions(-)

Don't forget to change the version number after branching!

Then, correct the error and make the commit the correction in one or more commit separated.

$ git commit -m "Fixed severe production problem"
# [hotfix-1.2.1 abbe5d6] Fixed severe production problem
# 5 files changed, 32 insertions(+), 17 deletions(-)

Finishing a hotfix branch

When finished, the bugfix needs to be merged back to the master, but it also needs to be incorporated again to develop, in order to ensure that the bugfix also be included in the next version. This is quite similar to how the Release branches are finalized.

First, update the master and tag the release [Select the summer]:

$ git checkout master
# Switched to branch ' master '
$ git merge --in-FF hotfix-1.2.1
# Merge made by recursive.
# (Summary of changes)
$ git tag -the 1.2.1

Note: You can also use the flags-s or-u to sign your tag cryptographically.

Then, include the bugfix in develop also:

$ git checkout develop
# Switched to branch ' develop '
$ git merge --in-FF hotfix-1.2.1
# Merge made by recursive.
# (Summary of changes)

The only exception to the rule here is that, When there is a release branch in progress, the changes of hotfix need to be merged to this release branch, instead of develop. Merge the bugfix in release branch will cause the bugfix be merged into the develop also, when the release branch is completed. (If the work on the develop immediately requires this bugfix and can't wait until the release branch is completed, you can surely merge the bugfix for deveolp, New Also.)

Finally, remove the branch Temporary:

$ git branch -d hotfix-1.2.1
# Deleted branch hotfix-1.2.1 (was abbe5d6).

Summary

Although there is nothing really extraordinary in this branching model, the figure at the beginning of the Post can be very useful in our projects. It shows an easy-to-understand mental model and allows team members to develop a common understanding of the processes of branching and Releasing.

A high-quality PDF version of the figure is provided on the blog of the original post: http://nvie.com/posts/a-successful-git-branching-model/ [or in the Download link below]. Go ahead and place it on the wall for a quick reference at any time.

Total hits: 7135

A comment on “A successful model of branches in Git

  1. Deivson Birth said:

    Good afternoon, I know that Git was initially developed by the Linux system but when speaking in portability, I wonder if the Git runs on windows and POSIX MSIS??

Leave a reply

The your email address will not be published. Required fields are marked with *