Search code examples
.netgitversioning

git branching strategy for .NET major versions and release branches


For my .NET project containing several class libraries, I am currently using the following git branching strategy:

                feature 1
             +------------+
           ^/              \
  master   /                v
----------+-+---+---------- PR ----+------+-----------
             \   \                  \      \
              \   v  release/7.0     \      v
               \  +------------------ \ ----+--------- I branched from master and set the "version" to 7.0.0, 7.0.1, ... The aspnetcore package versions also point to 7.x.x
                \                      \
                 v  release/6.0         v
                 +----------------------+------------- I branched from master and set the "version" to 6.0.0, 6.0.1, ... The aspnetcore package versions also point to 6.x.x

However, doing it like this prevents me from properly updating .NET versions on the master branch, since these changes would also need to be merged into the release branches. So the master branch would always be out-of-date.

I've read about GitFlow, but it's unclear to me how this solves the problem of version changes in the master branch being merged to all release branches.

If I use SourceTree to check the branch graph for asp.net core, I see that the main branch is never actually merged into the release/6.0 and release/7.0 branches, but commits still end up on these branches:

aspnetcore branch graph

The version was changed in the main branch to 8, but these changes don't propagate to the other release branches.

I've already read several resources in the past, but couldn't get an answer. So how do I properly organize my git repository in order to do versioning the right way?

EDIT

It seems that for angular, commits on the main branch manage to end up in the release branches, without actually merging them. But I'm wondering how they do this. The commit timestamp is 2 seconds apart, so I don't think they cherry-pick it manually

angular branch graph

QUESTIONS:

  • So when/where does the release process replace 0.0.0-PLACEHOLDER with the actual version, and where does that come from? Also, how do they map the corresponding dependency versions in that stage?
  • Are angular/asp.net core/... using git-flow? Or how do they manage multiple major versions next to one another?
  • Where is the version number coming from?

It seems to me that I'll have to change the version (+ the versions of the dependencies) on the master, and mark the commit to be skipped when merging into release branches... But is that feasible to do?

EDIT 2

LinkedIn posted an article on their dev blog about this, which points to an app to automate cherry-picking and creates pull requests. But there seem to be several github actions too.

Even google created a github bot to create pull requests to cherry-pick commits into release branches


Solution

  • There are many, many ways of managing branching strategies. I think for your purposes there are a couple of ways you could handle things.

    Cherry-picking: Whenever a feature/bugfix goes to master and should be backported to existing releases, explicitly cherry-pick the changes back to the relevant branch. In this model the release branches and master branch are never merged into each other. This gives full control over what changes end up in each branch. One risk is that you forget to cherry-pick the change into all relevant releases - you might remember to cherry-pick it to release/6.0 but forget about release/7.0.

    Making changes on the oldest affected release, and merging forward: Whenever a bugfix/feature is needed on a release branch, first merge the change to the oldest relevant release branch. Then merge that release branch to the next release branch (i.e. merge release/6.0 into release/7.0). Finally merge the most recent release branch into master. This avoids cherry-picking, so may be simpler. Also, it is easy to check that all desired changes have made it to each release - each release should be 0 commits ahead of the next release. It has the downside that you must decide which is the oldest release you are merging to ahead of time. If you later decide you want to merge the change to an older release, you end up cherry-picking the original change to the older release, then merging from that release through the newer releases which already have that change (so the merge commits are empty) purely to get back to having all releases 0 commits ahead of the next release. Worth noting is that in this model all version number changes occur on master, so you would increment the version on master immediately after taking a release branch.

    Gitflow branching model has both master and develop, so requires managing more branches than you currently do, so is probably overcomplicated for your needs.

    Both models I have suggested allow you to make arbitrary changes on master, since you never merge master into any release branch.

    Good luck with choosing a branching strategy that works for you.