Git Branching and Tagging
This topic had some critical errors and has been updated. Summary:
- Bug fixing:
- "Patch bugs" in the branch where you want it first released.
- "Merge UP" bug fixes from the bug fix branch to the master branch. NEVER merge master into a release branch.
- Minor features:
- Item branches:
- Base the Item (feature) branch on the branch where you first want it released. (ReleaseNNxNN or master)
- Merge the Item branch back into its base branch when the feature is "ready"
- NEVER cross merge from master into a release branch. If your feature branch started from master, it can only go back to master. But if it started from Release02x01, then it can be merged into master.
Unlike subversion, git development is done in multiple repositories. Subversion was a single monolithic repository containing all extensions, all releases, scratch workareas, etc.
- The foswiki account on github is somewhat like subversion
trunk. It contains all foswiki managed code, core and extensions. This account contains over 600 separate git repositories:
- The "distro" repository is the core Foswiki distribution. It contains the core code and all default extensions.
master branch equivalent to the
trunk code. It's the bleeding development edge.
Release* branches are the stable Foswiki releases, and the leading edge of patch development.
- Every other extension is separated out into it's own repository. This makes the checkout of foswiki code for developers much smaller than with subversion.
- A major release is a release where the first digit in the version number changes.
- A minor release is a release where the second digit in the version number. Patch releases changes the 3rd digit.
- A patch is a release of a set of changes to a previous software release that fixes one or more problems with that release. Patch releases are released as complete packages for new installations and cumulative packages with all the changed files since last major/minor release. (The idea is that an admin with a running installation can always simply copy the contents of a the package with the changed files on top of the installation without having to have installed all the previous patch releases that have been released since last major/minor release.)
This is the release process:
- All development of major/minor releases and all extensions is done in the git
"distro" repository, master branch.
- The first major/minor release is built from a new patch branch which is created soon after the release meeting agrees to declare feature freeze.
- It is a strict criteria that the new Patch branch is not created until ALL agreed features are implemented. We do not create the Patch branch in the middle of the implementation of complex features. This means that in the short period between declaration of feature freeze and the creation of the feature freeze the feature freeze also includes
- In the period between the creation of the Patch branch and the minor/major release all bug fixes to the core code and default extensions need to be checked into both
master and the new Patch branch.
- New features are only checked into the
master. Checking in new features into the
master is allowed again the minute the new Patch branch is created
- Each time an actual release is created (major/minor/patch) a git tag is created.
- The naming convention:
- We name the branches Release01x00, Release02x00... in branches
- We name the tags FoswikiRelease01x00x00, FoswikiRelease01x00x01, FoswikiRelease01x00x02.... in tags
More details on the release process
- A new Major/Minor Release branch is always created from
master. All major development happens there. Patches are not branched. They are tagged to create a stable environment to create releases from. See the Release branch as the current stable release branch
- All bug fixes are always applied to the oldest release branch that will get the fix.
- Patch releases (third decimal number) only contain fixes selected on the basis of these criteria:
- Security issues. Some risk is acceptable when implementing these. Urgency is important here.
- A bug is very severe and can cause a lot of trouble for the users and admins. Some risk is acceptable when implementing these.
- A bug is very common and annoying. Fix must be well tested for a while.
- Bugfix where code inspection and experience tells us that this bug could become serious
- A bug with a very simple fix with no practical risk.
- "upstream" bugs and updates that need to be incorporated (eg. JQuery code.
- Document changes that resolve issues that can have significant impact on some users. Doc updates are considered safe.
- The below kinds of changes should never be merged into a Release branch after a minor/major release and released in a patch release.
- Complex bug fixes with many lines of code and/or many sources files and not being a security issue or very severe bug.
- Changes to settings and preferences. Admins must be able to apply the package with the changed files without worrying that settings are reverted.
- Any kind of enhancements or new feature.
- Changes to plugins that are not in the standard release package.
Release branching timeline
┌─────────────feature3───────────────────────────┐ │ │
│ ┌─feature2───────────────────────────┐ │ │ │
│ ┌───────UNICODE────────────┐ │ │ │ │
│ │ │ │ │ │ │ │
│ ↕ ↕ │ │ | | |
│ │ │ | │ |
└───Release01x01─────█ │ ↕ ↕ │ | │ |
│ │ | └──▲───Release03x───>>
└───Release02x00──────────█ | |
| │ | |
| └──Release02x01──────▲─────!──▲─urgent bug─fix─>>
T 2.0.1 | |
T 2.1.0 T 2.1.1
◆ Today (22 Dec 2015)
┵ Branch to feature
▼ Merge in a feature
▲ Merge fixes back into master and other newer release branches
┭ Branch to a Release
█ Obsolete, all development stops
! Stable - routine bugfix stops.
↕ Cherry-pick fixes "down" from master
T Tag a patch release
Branches are created using either
git branch or
git checkout -b command
Branches in git are "lightweight". They are simply a pointer to a location in the development stream of commits.
See this blog entry
for a good description of git branching.
Fix a bug.
Strongly recommended: Fix it in the Branch where you want the fix to first appear. Ex. Release02x01 has a bug, and you want it fixed in the next patch.
git checkout Release02x01
git checkout -b Item12434 (Optional ... for complex fixes)
# Incorporate the fix into the release
git checkout Release02x01
git merge Item12434
# And merge up to master
git checkout master
git merge Release02x01
Following this flow, the commit will appear in all branches using the same commit ID. So it's possible to find where a fix exists.
Search for this patch: 591295a Item13981: update jquery.render
$ git branch --contains 591295a
Cherry-pick vs. Merging
- Merge takes all of the commits in a branch and incorporates them into another branch.
- You can only merge branches, never individual commits.
- Merge preserves the history, identifiers and ordering of commits.
- cherry pick applies a single commit to a branch.
- The commit message and author is preserved, but the commit ID changes
If you always fix on the "most stable" branch you can then always safely merge into master and _you should never need to cherry pick_
Assume you've made a complicated fix on a feature branch that also applies to the master and release branches. But you can't merge your features, and don't want to cut/paste your changes. Cherry-pick allows you to take a single commit and apply it to another branch.
We have made an important update that fixes Item90210
, commit 1b427fa which we want to apply to the current Release branch. You must not
use merge, because that will apply all changes between two branches. Use
to apply a single fix.
Current working directory is the local checkout copy of the release branch
git cherry-pick 1b427fa
Commit the changes and push it to the upstream repository
Put the Item90210
temporarily back into
state if it has been closed or waiting for release.
git commit -m "Item90210: Important hotfix of bug xyz applied to Release01x00 branch"
git pull --rebase && git push
Find out if anything was missed
Git makes one horrendous task simple
- What fixes are were made to "branch 1" that are missing from "branch 2"
cherry-pick!) is used to compare two branches to determine if there are any missing commits.
# Check if there are any fixes on Release02x01 that were not made to master
$ git cherry master Release02x01
$ git show c86d573bdb02355c31a642ab202acd54950834f6
... Item14143: Recommend setting of SafeEnvPath ...
In this case, a merge was missed and there is a missing fix. However, in the other direction,
git cherry Release02x01 master
, it lists 181 master commits that are not in Release02x01. That's expected. but not useful.