This document was written in order to unify the internal company GitFlow rules. This method is not introducing pure GitFlow, as it is a mix of both GitFlow and GitLab Flow, with best company practices worked over many years. It helps to keep a clean and readable history of the repository and better control over changes and project lifecycles.
After initializing the repository, create a develop and master branch if it wasn’t included by default. The develop branch should contain a development code that is a mirror of the master branch with new features included. The master contains a stable version of code, representing the production state. Both have infinite lifetimes, and in comparison to other branches in Git Flow, will never be removed. Set up proper protection rules: require to pull request reviews before merging and require status checks to pass before merging. You may also consider allowing only chosen team members to merge changes to the master.
NOTE: Sometimes it is important for the project to add more infinite branches, for example, to represent available environments. However, keep the “rule of two” if possible.
When starting to work with a given feature, first ensure you have your develop branch synced.
Then, checkout to your feature branch. Name it respectively to the given schema: feature-JIRA-TASK-ID or you can also break that rule and name it differently. In this case, ensure that it does not conflict with patterns reserved for release, hotfix, bugfix, development or the master branch. Keeping JIRA task IDs will help you manage your feature branches more effectively.
This branch should exist as long as the given feature is developed and then merged to the parent branch. To commit to your local branch, please follow this command:
It is recommended that you add more commits to your local branch, following the “Commit early and often” rule. However, in the end, they must be squashed into a single commit representing a JIRA Task. Often committing will help you to manage your development history. When the feature is ready, it is time to open a Pull Request to develop a branch. First, you may push your local branch if it wasn’t pushed too far:
When the branch is ready, open your pull request on GitHub, by following this article: https://help.github.com/en/articles/creating-a-pull-request
Before opening a pull request, please ensure the following:
– a proper description has been given – usually, you would link your JIRA task, but you may also include some useful information related to the current code
– CircleCI steps were passed successfully
– your team members were assigned – it is good practice to include all your team members as assignees
– the reviewers were selected – the number of reviewers depends on your team
– your code is actually ready for review – take a last look at your code, think again if there is anything left to refactor, test it locally and ensure that it is ready for further steps.
– there are no merge conflicts and a branch is up-to-date with develop – if there are any, resolve them first
– keep only important commits – each commit should be represented by JIRA task, for example, JIRA-TASK-ID: New feature configuration; others should be squashed while rebasing your branch with the develop branch
– you have the proper destination branch selected
– you don’t forget to change the status of your JIRA task
Merging feature branch
It is time to merge your changes to develop branch when:
– the pull request was approved by selected team members
– all tests finished successfully
– there are no merge conflicts and the commit history looks fine
This can be done by either the project manager or feature developer. In order to perform the merge, follow these steps:
Now, JIRA task status can be changed.
Release branches should be created by a person responsible for the current release. Usually, releases are created periodically, for example, according to the sprint lifecycle.
Giving a release branch a proper name and corresponding tag is not an easy task at the very beginning. It is good practice to start using semantic versioning (https://semver.org/) which allows better control and makes reading the git history easier. The version string is constructed according to MAJOR.MINOR.PATCH schema:
– MAJOR – change representing incompatible API changes
– MINOR – adding new features in a backwards-compatible manner
– PATCH – adding backwards-compatible bug fixes
You may also use special suffixes, such as those representing beta or legacy branches, or create pre-releases. In that case, name it properly, e.g. 1.1.0-beta.4, 1.1.0-beta.5 or 1.1.0-alpha.
Making a release
The release branch should be a child of develop and could contain only commits connected with bugfixes.
The branch name should be based on the release version, with the release- prefix: release-MAJOR.MINOR.PATCH. The release branch should be fully tested both automatically and manually on the staging environment. If bugs occur, this is the last opportunity to push proper fixes and re-run the whole process, as long as it won’t be positively checked and ready for further processing. Then, the release commit should be pushed, with changes of the current release version string in files, such as package.json. It should also have an impact on the CHANGELOG.md file. This will help you track all changes before a proper release and prepare the content for GitHub release when the merge process is completed. The single file update should consist of all release changes grouped into three categories: features, fixes and maintenance.
In the first step however, make sure you have both of your develop and master branches up-to-date.
At this point, one may decide to create another pull request to the master with the release branch. It may be a good idea to run an additional check if all tests pass well on the remote machine.
Then go to the GitHub releases page and press the “Draft new release” button. In the displayed form, select the current version tag, set the release title similar to the release commit (Product Name M.M.P release) and a proper description, based on the CHANGELOG.md file. For public projects, the description should contain a list of all PR included in the current release.
In case some bugfixes were applied on the release branch, ensure you have your develop branch updated:
Hotfixes and Bugfixes
The main difference between a bug and hot fixes is their target branches.
Bug fixes should patch release branches as the only form of updating code before merging it to master. First, create the branch from the current feature branch. Make sure you have it up-to-date locally.
Then commit the necessary changes. After the process is finished, create a pull request and target it to the release branch. Follow guidance from the feature branch section. Your final commit title should match the given schema: “Bugfix M.M.P: Problem essence fix”. When the pull request is approved, it is time to merge it to the current release.
In order to perform a hotfix on the master branch, very similar steps to a bugfix must be taken, keeping in mind that the target branch is now the master branch.
Then, follow the usual development steps and when the process is finished, create a pull request with the master branch as a target. Keep in mind that the final commit should match the given schema “Hotfix X.Y.(Z + 1): Problem essence fix”. When every checkpoint has passed successfully, perform a merge to master. These steps differ from the one presented for a bugfix, as we need to bump the current release version.