63

I'm trying to choose a Git workflow that is most appropriate for our product. Here are the parameters:

  • We do a few major releases a year, let's say 10 at the most
  • We have multiple versions of our product active at the same time (some people are on v10.1, some on v11.2, etc.)
  • We need to be able to work on multiple releases at the same time (so we could be working on v12.1, but as we get to the end of the release we start working on v12.2 at the same time)
  • We need to be able to hotfix releases when critical bugs are found

So far, here's the way I think it could work:

  • Single remote repo is used
  • Create branch 12.1 from master
  • Create feature branches based on 12.1, commit them and merge back into 12.1, push
  • Once we need to start working on future release, create a new branch 12.2 based on 12.1
  • From then on, when working on a feature for 12.1, create branch from 12.1, commit changes, and merge into both 12.1 and 12.2, push
  • If working on a feature for 12.2, create branch from 12.2, commit changes, and merge only into 12.2, push
  • When release 12.1 is completed, merge it into master and tag master branch with 12.1
  • If a hotfix is needed, create a hotfix branch from oldest release branch that needs it, commit changes, and merge back into all release branches for that release and future releases that could be affected; if the latest stable release branch was affected, merge it into master.

I have a few concerns:

  • I'm not sure that merging hotfixes from old branches into new branches will be a smooth process, especially if there have been a lot of overlapping changes; would it be smarter to just hotfix manually in each branch in cases where it looks like there will be conflicts
  • The workflow models I've seen seem to not keep release branches alive much, once done the release gets merged into master, tagged, and removed. My problem with that is that I don't have a good idea how to manage the state of the release if all I have are tags in master, seems easier to hotfix in a branch and then I have a release I can always go back to that has the latest hotfix (I can even tag the hotfixes in the release). Not sure there's a way I could go back within master and somehow have a copy of the release with hotfixes applied and update that tag.

Comments are appreciated on things I may have overlooked or better ways of accomplishing things given the requirements I've specified.

4
  • 4
    nvie.com/posts/a-successful-git-branching-model
    – Wilbert
    Commented Jan 16, 2015 at 16:50
  • 25
    I'm aware of git-flow, but I don't see how it addresses working on multiple simulataneous releases. Seems like release branches aren't even really made to do any work on, mostly to do cleanup and then merge and tag. What do I do when I have a hotfix that affects 4 different release versions? I guess I could checkout a tagged release from master, but once I've made fixes to it, how would I re-work whatever fixes I've made into master for that particular release. Seems like it would be rather difficult.
    – Rocket04
    Commented Jan 16, 2015 at 17:37
  • 4
    If you need to hot fix multiple releases with the same fix, you should probably fix the oldest version first and merge up to newer, adapting to fit for each release. If you work from new to old you risk pulling down dependencies from later releases which will complicate things.
    – axl
    Commented Feb 29, 2016 at 4:55
  • And as I mention in my proposed answer, the master branch doesn't work so well with multiple live releases, so unless you really need it for some reason, I would advice you not to use it.
    – axl
    Commented Feb 29, 2016 at 4:57

4 Answers 4

26

You seem to be branching off on every major release (12.0.0), then having possible minor updates to each (12.1.0), and hot fixes (12.2.1). Correct?

There's no specific reason why you cannot keep release branches alive in GitFlow after a release is out, other than the fact that coordinating changes between multiple diverging branches for a long time is hard with any model. I suppose GitFlow was also modeled more for products that maintain a single live release while developing the next.

I would stick with GitFlow and make a few amendments;

Skip the master branch. I've had no practical use of it so far, and it would lose its linearity the way you work. Keep development on the next major release on develop. If you decide to keep master, don't put release tags on master, put them on the last commit on the release branch that produced the binary you're shipping.

Don't throw away the release branches after you merge them back to develop. Instead keep them around for the next minor release and possible hot fixes. If you ever stop supporting a release, I suppose it's fine to delete them. You could name release branches after their main component, release/12, and then create sub-release branches, release/12.1, release/12.2 off of it. I've not had to worry too much about this level of parallelism, but that's probably what I'd try. You can think of each major release branch as its own sub-GitFlow environment in this case.

If you must be working in parallel on features for several future major releases at the same time, perhaps you have to keep the next one (13) on develop and anything for later versions (14, 15) on additional "develop-N" branches. That does seem very hard to maintain in general, but would be possible.

1
  • But if you're maintaining a single release, then you don't need other branches anyway. Just the master branch. So there's no point in using git-flow then...
    – Pieterjan
    Commented Aug 11, 2023 at 6:01
5

It seems that a possible solution for your main problem («We need to be able to work on multiple releases at the same time [...]») is dooing a git worktree add <path> [<branch>]

A git repository can support multiple working trees, allowing you to check out more than one branch at a time.
With git worktree add, a new working tree is associated with the repository.

This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "git clone".
A repository has one main working tree (if it's not a bare repository) and zero or more linked working trees.

See this SO answer for a detailed introduction on git worktree.

3

You mentioned that you are familiar with gitflow. I suggest to addopt it for your scenario. You will need to create branches from your development branch to support older versions. These older versions will also need to have their own release/master branches and hotfix branches. You will need to periodically merge your support branches into the newer support branches and the develop branch.

As the development of the major versions diverges this will keep getting harder. There is no silver bullet for this. Sometimes it will be easier to make changes manually. The cost of maintaining the older versions will increase, and at some point it won't worth it anymore.

It all depends an what kind of changes you are making in your older versions. If only bugfixing, thats relatively easy to merge. If you try adding new features, that will be hard.

2
  • But as I mentioned, in the case of git-flow it doesn't seem like they use release branches for much at all. It didn't sound like there's any major development that goes on there. It also seems like the develop branch is kind of useless if we're mostly working in release branches, might as well just get rid of it, each release branch is essentially a develop branch for a certain period of time. Or am I missing something?
    – Rocket04
    Commented Jan 19, 2015 at 17:12
  • "each release branch is essentially a develop branch" No it is not. In a git flow model ideally you do NOT add features to a release branch, only bug fixes. Commented Dec 11, 2019 at 10:05
2

I’ve been looking at “A stable mainline branching model for Git” which I think has the potential to solve this problem nicely.

To summarize:

  • Single branch for development (master). Features branch from master and are merged back to master
  • When master is stable and ready for a release, branch off to e.g. release/1.0 and tag the commit as a release candidate
  • QA the release branch
  • Make updates and new release candidates as necessary on the release/1.0 branch
  • Eventually tag v1.0.0
  • Never merge release branches back into master
  • Meanwhile, feature development has not stopped on master for the next release
  • Hotfixes are ideally made on master and cherry-picked to release branches. If that’s impossible, hotfixes can be made on the release branch itself and a ticket should be made to fix the problem properly in master.

visual depiction of branching model as described

The article has a lot more detail about different scenarios with this model and how to solve them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.