Git Common-Flow 1.0.0-rc.5
-Introduction
-Common-Flow is an attempt to gather a sensible selection of the most common -usage patterns of git into a single and concise specification. It is based on -the original variant -of GitHub Flow, while taking -into account how a lot of open source projects most commonly use git.
-In short, Common-Flow is essentially GitHub Flow with the addition of versioned -releases, optional release branches, and without the requirement to deploy to -production all the time.
-Summary
--
-
- The “master” branch is the mainline branch with latest changes, and must not -be broken. -
- Changes (features, bugfixes, etc.) are done on “change branches” created from -the master branch. -
- Rebase change branches early and often. -
- When a change branch is stable and ready, it is merged back in to master. -
- A release is just a git tag who’s name is the exact release version string -(e.g. “2.11.4”). -
- Release branches can be used to avoid change freezes on master. They are not -required, instead they are available if you need them. -
Terminology
--
-
- Master Branch - Must be named “master”, must always have passing tests, -and is not guaranteed to always work in production environments. -
- Change Branches - Any branch that introduces changes like a new feature, a -bug fix, etc. -
- Source Branch - The branch that a change branch was created from. New -changes in the source branch should be incorporated into the change branch via -rebasing. -
- Merge Target - A branch that is the intended merge target for a change -branch. Typically the merge target branch will be the same as the source -branch. -
- Pull Request - A means of requesting that a change branch is merged in to -its merge target, allowing others to review, discuss and approve the changes. -
- Release - May be considered safe to use in production environments. Is -effectively just a git tag named after the version of the release. -
- Release Branches - Used both for short-term preparations of a release, and -also for long-term maintenance of older version. -
Git Common-Flow Specification (Common-Flow)
-The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, -“SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be -interpreted as described in RFC 2119.
--
-
- TL;DR
-
-
-
- Do not break the master branch. -
- A release is a git tag. -
- - The Master Branch
-
-
-
- A branch named “master” MUST exist and it MUST be referred to as the -“master branch”. -
- The master branch MUST always be in a non-broken state with its test -suite passing. -
- The master branch IS NOT guaranteed to always work in production -environments. Despite test suites passing it may at times contain -unfinished work. Only releases may be considered safe for production use. -
- The master branch SHOULD always be in a “as near as possibly ready for -release/production” state to reduce any friction with creating a new -release. -
- - Change Branches
-
-
-
- Each change (feature, bugfix, etc.) MUST be performed on separate -branches that SHOULD be referred to as “change branches”. -
- All change branches MUST have descriptive names. -
- It is RECOMMENDED that you commit often locally, and that you try and -keep the commits reasonably structured to avoid a messy and confusing git -history. -
- You SHOULD regularly push your work to the same named branch on the -remote server. -
- You SHOULD create separate change branches for each distinctly different -change. You SHOULD NOT include multiple unrelated changes into a single -change branch. -
- When a change branch is created, the branch that it is created from -SHOULD be referred to as the “source branch”. Each change branch also -needs a designated “merge target” branch, typically this will be the same -as the source branch. -
- Change branches MUST be regularly updated with any changes from their -source branch. This MUST be done by rebasing the change branch on top of -the source branch. -
- After updating a change branch from its source branch you MUST push the -change branch to the remote server. Due to the nature of rebasing, you -will be required to do a force push, and you MUST use the -“—force-with-lease” git push option when doing so instead of the regular -“—force”. -
- If there is a truly valid technical reason to not use rebase when -updating change branches, then you can update change branches via merge -instead of rebase. The decision to use merge MUST only be taken after all -possible options to use rebase have been tried and failed. People not -understanding how to use rebase is NOT a valid reason to use merge. If -you do decide to use merge instead of rebase, you MUST NOT use a mixture -of both methods, pick one and stick to it. -
- - Pull Requests
-
-
-
- To merge a change branch into its merge target, you MUST open a “pull -request” (or equivalent). -
- The purpose of a pull request is to allow others to review your changes -and give feedback. You can then fix any issues, complaints, and more that -might arise, and then let people review again. -
- Before creating a pull request, it is RECOMMENDED that you consider the -state of your change branch’s commit history. If it is messy and -confusing, it might be a good idea to rebase your branch with “git rebase --i” to present a cleaner and easier to follow commit history for your -reviewers. -
- A pull request MUST only be merged when the change branch is up-to-date -with its source branch, the test suite is passing, and you and others are -happy with the change. This is especially important if the merge target -is the master branch. -
- To get feedback, help, or generally just discuss a change branch with -others, it is RECOMMENDED you create a pull request and discuss the -changes with others there. This leaves a clear and visible history of -how, when, and why the code looks and behaves the way it does. -
- - Versioning
-
-
-
- A “version string” is a typically mostly numeric string that identifies a -specific version of a project. The version string itself MUST NOT have a -“v” prefix, but the version string can be displayed with a “v” prefix to -indicate it is a version that is being referred to. -
- The source of truth for a project’s version MUST be a git tag with a name -based on the version string. This kind of tag MUST be referred to as a -“release tag”. -
- It is OPTIONAL, but RECOMMENDED to also keep the version string -hard-coded somewhere in the project code-base. -
- If you hard-code the version string into the code-base, it is RECOMMENDED -that you do so in a file called “VERSION” located in the root of the -project. But be mindful of the conventions of your programming language -and community when choosing if, where and how to hard-code the version -string. -
- If you are using a “VERSION” file in the root of the project, this file -MUST only contain the exact version string, meaning it MUST NOT have a -“v” prefix. For example “v2.11.4” is bad, and “2.11.4” is good. -
- It is OPTIONAL, but RECOMMENDED that that the version string follows -Semantic Versioning (http://semver.org/). -
- - Releases
-
-
-
- To create a new release, you MUST create a git tag named as the exact -version string of the release. This kind of tag MUST be referred to as a -“release tag”. -
- The release tag name can OPTIONALLY be prefixed with “v”. For example the -tag name can be either “2.11.4” or “v2.11.4”. It is however RECOMMENDED -that you do not use a “v” prefix. You MUST NOT use a mixture of “v” -prefixed and non-prefixed tags. Pick one form and stick to it. -
- If the version string is hard-coded into the code-base, you MUST create a -“version bump” commit which changes the hard-coded version string of the -project. -
- When using version bump commits, the release tag MUST be placed on the -version bump commit. -
- If you are not using a release branch, then the release tag, and if -relevant the version bump commit, MUST be created directly on the master -branch. -
- The version bump commit SHOULD have a commit message title of “Bump -version to VERSION”. For example, if the new version string is “2.11.4”, -the first line of the commit message SHOULD read: “Bump version to -2.11.4” -
- It is RECOMMENDED that release tags are lightweight tags, but you can -OPTIONALLY use annotated tags if you want to include changelog -information in the release tag itself. -
- If you use annotated release tags, the first line of the annotation -SHOULD read “Release VERSION”. For example for version “2.11.4” the first -line of the tag annotation SHOULD read “Release 2.11.4”. The second line -MUST be blank, and the changelog MUST start on the third line. -
- - Short-Term Release Branches
-
-
-
- Any branch that has a name starting with “release-” SHOULD be referred to -as a “release branch”. -
- Any release branch which has a name ending with a specific version -string, MUST be referred to as a “short-term release branch”. -
- Use of short-term release branches are OPTIONAL, and intended to be used -to create a specific versioned release. -
- A short-term release branch is RECOMMENDED if there is a lengthy -pre-release verification process to avoid a code freeze on the master -branch. -
- Short-term release branches MUST have a name of “release-VERSION”. For -example for version “2.11.4” the release branch name MUST be -“release-2.11.4”. -
- When using a short-term release branch to create a release, the release -tag and if used, version bump commit, MUST be placed directly on the -short-term release branch itself. -
- Only very minor changes should be performed on a short-term release -branch directly. Any larger changes SHOULD be done in the master branch, -and SHOULD be pulled into the release branch by rebasing it on top of the -master branch the same way a change branch pulls in updates from its -source branch. -
- After a release tag has been created, the release branch MUST be merged -back into its source branch and then deleted. Typically the source branch -will be the master branch. -
- - Long-term Release Branches
-
-
-
- Any release branch which has a name ending with a non-specific version -string, MUST be referred to as a “long-term release branch”. For example -“release-2.11” is a long-term release branch, while “release-2.11.4” is a -short-term release branch. -
- Use of long-term release branches are OPTIONAL, and intended for work on -versions which are not currently part of the master branch. Typically -this is useful when you need to create a new maintenance release for a -older version. -
- A long-term release branch MUST have a name with a non-specific version -number. For example a long-term release branch for creating new 2.9.x -releases MUST be named “release-2.9”. -
- Long-term release branches for maintenance releases of older versions -MUST be created from the relevant release tag. For example if the master -branch is on version 2.11.4 and there is a security fix for all 2.9.x -releases, the latest of which is “2.9.7”. Create a new branch called -“release-2.9” from the “2.9.7” release tag. The security fix release will -then end up being version “2.9.8”. -
- To create a new release from a long-term release branch, you MUST follow -the same process as a release from the master branch, except the -long-term release branch takes the place of the master branch. -
- A long-term release branch should be treated with the same respect as the -master branch. It is effectively the master branch for the release series -in question. Meaning it MUST always be in a non-broken state, MUST NOT be -force pushed to, etc. -
- - Bug Fixes & Rollback
-
-
-
- You MUST NOT under any circumstances force push to the master branch or -to long-term release branches. -
- If a change branch which has been merged into the master branch is found -to have a bug in it, the bug fix work MUST be done as a new separate -change branch and MUST follow the same workflow as any other change -branch. -
- If a change branch is wrongfully merged into master, or for any other -reason the merge must be undone, you MUST undo the merge by reverting the -merge commit itself. Effectively creating a new commit that reverses all -the relevant changes. -
- - Git Best Practices
-
-
-
- All commit messages SHOULD follow the Commit Guidelines and format from -the official git -documentation: -https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines -
- You SHOULD never blindly commit all changes with “git commit -a”. It is -RECOMMENDED you use “git add -i” or “git add -p” to add individual -changes to the staging area so you are fully aware of what you are -committing. -
- You SHOULD always use “—force-with-lease” when doing a force push. The -regular “—force” option is dangerous and destructive. More -information: -https://developer.atlassian.com/blog/2015/04/force-with-lease/ -
- You SHOULD understand and be comfortable with -rebasing: https://git-scm.com/book/en/v2/Git-Branching-Rebasing -
- It is RECOMMENDED that you always do “git pull —rebase” instead of “git -pull” to avoid unnecessary merge commits. You can make this the default -behavior of “git pull” with “git config —global pull.rebase true”. -
- It is RECOMMENDED that all branches be merged using “git merge —no-ff”. -This makes sure the reference to the original branch is kept in the -commits, allows one to revert a merge by reverting a single merge commit, -and creates a merge commit to mark the integration of the branch with -master. -
-
FAQ
-Why use Common-Flow instead of Git Flow, and how does it differ?
-Common-Flow tries to be a lot less complicated than Git Flow by having fewer -types of branches, and simpler rules. Normal day to day development doesn’t -really change much:
--
-
- You create change branches instead of feature branches, without the need of a -“feature/” or “change/” prefix in the branch name. -
- Change branches are typically created from and merged back into “master” -instead of “develop”. -
- Creating a release is done by simply creating a git tag, typically on the -master branch. -
In detail, the main differences between Git Flow and Common-Flow are:
--
-
- There is no “develop” branch, there is only a “master” branch which contains -the latest work. In Git Flow the master branch effectively ends up just being -a pointer to the latest release, despite the fact that Git Flow includes -release tags too. In Common-Flow you just look at the tags to find the latest -release. -
- There are no “feature” or “hotfix” branches, there’s only “change” -branches. Any branch that is not master and introduces changes is a change -branch. Change branches also don’t have a enforced naming convention, they -just have to have a “descriptive name”. This makes things simpler and allows -more flexibility. -
- Release branches are available, but optional. Instead of enforcing the use of -release branches like Git Flow, Common-Flow only recommends the use of release -branches when it makes things easier. If creating a new release by tagging -“master” works for you, great, do that. -
Why use Common-Flow instead of GitHub Flow, and how does it differ?
-Common-Flow is essentially GitHub Flow with the addition of a “Release” concept -that uses tags. It also attempts to define how certain common tasks are done, -like updating change/feature branches from their source branches for -example. This is to help end arguments about how such things are done.
-If a deployment/release for you is just getting the latest code in the master -branch out, without caring about bumping version numbers or anything, then -GitHub Flow is a good fit for you, and you probably don’t need the extras of -Common-Flow.
-However if your deployments/releases have specific version numbers, then -Common-Flow gives you a simple set of rules of how to create and manage -releases, on top of what GitHub Flow already does.
-What does “descriptive name” mean for change branches?
-It means what it sounds like. The name should be descriptive, as in by just -reading the name of the branch you should understand what the branch’s purpose -is and what it does. Here’s a few examples:
--
-
- add-2fa-support -
- fix-login-issue -
- remove-sort-by-middle-name-functionality -
- update-font-awesome -
- change-search-behavior -
- improve-pagination-performance -
- tweak-footer-style -
Notice how none of these have any prefixes like “feature/” or “hotfix/”, they’re -not needed when branch names are properly descriptive. However there’s nothing -to say you can’t use such prefixes if you want.
-You can also add ticket numbers to the branch name if your team/org has that as -part of it’s process. But it is recommended that ticket numbers are added to the -end of the branch name. The ticket number is essentially metadata, so put it at -the end and out of the way of humans trying to read the descriptive name from -left to right.
-How do we release an emergency hotfix when the master branch is broken?
-This should ideally never happen, however if it does you can do one of the -following:
--
-
- Review why the master branch is broken and revert the changes that caused the -issues. Then apply the hotfix and release. -
- Or use a short-term release branch created from the latest release tag instead -of the master branch. Apply the hotfix to the release branch, create a release -tag on the release branch, and then merge it back into master. -
In this situation, it is recommended you try to revert the offending changes -that’s preventing a new release from master. But if that proves to be a -complicated task and you’re short on time, a short-term release branch gives you -a instant fix to the situation at hand, and let’s you resolve the issues with -the master branch when you have more time on your hands.
-About
-The Git Common-Flow specification is authored -by Jim Myhrberg.
-If you’d like to leave feedback, -please open an issue on GitHub.
-