This is based on the renowned Gitflow Workflow by Vincent Driessen.

Git repositories aren’t technically centralized anywhere but you could refer to one as the “source of truth.” Typically this called “origin” but development teams who are working on a giant feature together could define their own Git remote for other teammates before pushing to origin.

Typically when you’re coding, you’re either building a new feature or fixing a bug. When both need to happen at once, that’s when things get interesting.

Typically you’ll have two main immortal branches. These are the branches changes are pushed to (git push):

  • master
    • Contains an abridged version of the project
    • HEAD should always be production-ready
    • Make sure you tag each commit with a version number.
  • development
    • Contains the entire history of the project
    • HEAD contains latest changes for next release (nightly builds)

Once source code in the development branch is stable, it is merged into master and tagged with a release number to represent a new production release.

It’s good practice to pull with: git pull –rebase to avoid useless merge commits. You could modify .gitconfig to have this done automatically.

It’s also good practice to initiate a pull request before merging into development/master.

I recommend using this extension to make your life easier: https://github.com/petervanderdoes/gitflow

Version Naming Conventions

  • [Major version].[Minor version].[Build Number]
  • [Year].[Month].[Day].[Build]
  • Major.Minor.Hotfix

Support Branches

These branches are typically broken into the following:

Topic/Feature branches

  • Flow
    • Should only exist in the developer’s local repository, not on origin.
    • Branch off from development branch
    • Must be merged back into the development branch
  • Create
    • git checkout -b newfeature123 development
  • Merge
    • git checkout development
    • git merge –no-ff newfeature123
      • It does create a empty commit object but the trade-off is worth it. We don’t fast-forward because we want to keep historical information about the feature branch and all its commits that create the feature. This also makes it easier if you need to revert a whole feature.
    • git branch -d newfeature123
    • git push origin development

Release branches

These branches are created once the development branch has all the required feature for the expected release. Release branches are great because it allows one team to polish up the release before it gets merged into the master while other teams could work on new features of a future release. It also allows an easy view of the preparation of the release. Once the branch is created, no additional features are allowed. These are allowed:

  • bug fixes
  • documentation generation
  • other release-oriented tasks

It also helps Primarily prepares code for production release. Allows for last minute changes, minor bug fixes, and prepping version number, build dates, etc for release. The perfect time to branch off from development into a release branch is when all features targeted for the next release is merged into the development branch. Only when the release branch is created is a version number for the release is assigned.

  • Flow
    • Could branch off of the development branch
    • Merges back to develop and master branches
    • Naming convention: release-*
  • Create
    • git checkout -b release-1.3 development
    • git commit -am “Bump version number to 1.3”
  • Merge
    • git checkout master
    • git merge –no-ff release-1.3
    • git tag -a 1.3 -m “Release v1.3” (sign with -s or -u <key>)
      • When merging to master, always tag.
    • git push –tags
      • Keep in mind annotated tags aren’t tied to a specific branch, but are objects of their own with metadata. It contains the commit, tagger, date, author, etc. Lightweight tags are basically pointers to a commit hash. Here is an example of a annotated tag:
      • Tagger: John Doe <john@doe.com>
        Date: Fri Aug 14 04:39:17 2015 +0000
        First release with ICD-10 Support
        commit 1590c3a6b71232146192c8ab6dc3db5d79d8Merge: 6723e49 e4870c2
        Author: John Doe <john@doe.com>
        Date: Fri Aug 14 04:28:10 2015 +0000 
        Merge branch 'icd10-prep' into develop
    • git checkout develop
    • git merge –no-ff release-1.3
      • This may introduce a merge conflict due to version change to which you fix and commit again.
    • git branch -d release-1.3

Hotfix branches

These are the only branches that could branch from master. When there’s an emergency fix that needs to take place, you need to branch off of the current production tag that’s on the master branch. This way developers could continue to work on the development branch while others could work on a critical bug fix without affecting them (development could be unstable at the time the fix is needed). In a way this is very similar to the Release branches.

  • Flow
    • Branches off of master
    • Merges back into development and master
    • Naming convention: hotfix-*
  • Create (Assuming fix is on version 1.3)
    • git checkout -b hotfix-1.3.1 master
    • bump the version
    • git commit a-m “Bump version number to 1.3.1”
    • fix bug
    • git commit -m “Fix bug on production”
  • Merge
    • git checkout master
    • git merge –no-ff hotfix-1.3.1
    • git tag -a 1.3 -m “Hotfix v1.3.1” (sign with -s or -u <key>)
      • When merging to master, always tag.
    • git push –tags
    • git checkout development
    • git merge –no-ff hotfix-1.3.1
      • Keep in mind if a release branch exists, the hotfix should be merged to that branch and not development. Only merge into development if the bug is a show stopper.
    • git branch -d hotfix-1.3.1