Git
Gitflow
This should be used if your code should have multiple versions on productions. (i.e. android/ios, libraries)
Gitflow is based on two primary branches and several branch types to change the primary two. All branches except the primary ones are usually published as pull requests/merge_requests to be reviewed and merged.
In repositories following this workflow the default branch should be set to develop.
Primary branches
master: stable. In use on production and sandbox/staging stacks.develop: development. In use on testing stacks.
A merge to any of these two branches usually causes a deployment to all the corresponding stacks.
Feature branches (feature -> develop)
Branches where most of development work happens. Usually starts from develop. Belongs to a single person, and that person is free to do anything with it, including commit rewriting and force-pushing.
In order to maintain a clean list of features in commit log it is often a good idea to squash the contents of the feature branch into a single commit before merging it, or to use "Squash and merge" mode on GitHub/GitLab for the merge.
Once a feature branch is merged, its feature is considered ready for release. In high-development-traffic projects you should assume that releases can happen at any time. Therefore, features that might not be ready for production should not be merged even into develop. Use a GitHub/GitLab label on hold to signal this state for a pull request and outline the reason for that in the description.
While rare, feature branches may be nested. It's handy when development can go in parallel but needs a common base. Such "branches of feature branches" can be referred to as "topic branches".
Release branches (develop -> release -> master)
A preferred way of getting changes to production.
// TODO add more detailed steps per language/tool. (maven, gradle, nodejs, etc...)
May be started from develop and filed as a pull request to master. create-release can create the branch, extract the changelog and create a pull request on GitHub all in a single command.
Once a release branch is merged into master branch, tag-release can be used to create a corresponding GitHub release.
The preferred way of merging release branches is with a merge commit. This is to make sure that:
- existence of commits from
developcan still be tracked when preparing releases in the future (which rules out rebases because they might change existing commits and lose track of them) - in case of emergency a release can be easily reverted (which is easiest to do given a single commit)
Note that because merge commits are normally not pushed into develop branch, it's perfectly normal for master to be one commit ahead of develop. Merge commits do not need to be backported to develop.
Traditional Gitflow also allows "polishing" releases with additional fixes; we shouldn't do that, instead we strive to keep develop ready for release at all times.
Hotfix branches (hotfix -> master, then hotfix -> develop)
For especially urgent fixes, typically intended for production. May be started from the master branch.
Once merged into master, a hotfix needs to be backported to develop.
Force pushes
Never force push to the master or develop branches. For most repositories, this action is disabled by GitHub, but it's better to avoid this in the first place.
Back-porting hotfixes
Hotfix branches go against master and are merged against master. Whenever a hotfix gets merged, we also need to back-port the commit to develop.
You should do this by identifying the commit that needs to be back-ported, simply merge it into develop and push develop upstream.
Avoid cherry-picking the hotfix commit, as this will produce a different commit (same changes, but different commit SHA). If you do that, git might not detect the presence of this change when comparing branches and show it "twice".
Simplified flow (GitHub flow)
Based around a single primary branch (master) and feature branches, it's recommended for projects that are not too dependent upon by the rest of the system.
In repositories following this workflow the default branch should be set to master.
Compared to Gitflow above:
- hotfixes don't exist as a concept, since they are equivalent to features
- releases do not exist at all, every single feature is released as soon as it is merged
masterbranch is deployed to all primary stacks where the project is in use:- first to development
- then (if nothing went wrong) to sandbox, staging and production
Commit messages
Commit messages should contain the ticket number inside square brackets.
The commit message should be descriptive enough to pin-point the change.
Here are some examples:
# A Jira ticket
[BUGS-1234] Fixed the image upload
# If you don't have a ticket for your feature, you can mark it as such
[No ticket] Refactoring the Upload service