143

I've noticed something lately looking at some popular projects on GitHub, that there's no develop branch. And in fact, the GitHub Flow guide doesn't mention it either. From my understanding, master should always be totally stable and reflect production. If developers are working on feature branches, and then merging those into master when they're done, that means there's a period of time where features/fixes are being merged into master and the master branch is actually newer than production.

Wouldn't it make more sense to have the team create feature/fix branches off of develop, merge back into that, and then when the next version is totally ready for release, develop is merged into master and a tag is created? Imagine if people are merging straight into master, and a bug is reported in production that becomes difficult to fix because the master branch codebase has changed significantly. Then the devs just have to tell the user to wait until the next release to see the issue resolved.

EDIT: This question is different than "to branch or not to branch." It specifically addresses people moving away from using the develop branch and the reasons surrounding that, since that was touted as a best practice for a long time.

7
  • 12
    There are many possible workflows that git enables. One shouldn't expect gitflow or github flow to be used for all projects.
    – user40980
    Commented Mar 7, 2016 at 19:38
  • 8
    I hate the concept that master is a record of what is in production. If we need to know what is in production, we should just query production and not rely on master accurately reflecting what is in production.
    – Jim V
    Commented Jun 11, 2018 at 23:29
  • 5
    @JimV If none of your branches reflect production how could you ever create hotfix branches? Relying on a production server as an authoritative source for development seems like a really bad idea. You server could corrupt files or a hacker can insert a backdoor, and your repo would be infected. If it's not in the repo then it might as well not exist. Commented Nov 9, 2019 at 4:20
  • 5
    @AyexeM from the commit that reflects production, create the hotfix branch.
    – Jim V
    Commented Nov 9, 2019 at 6:48
  • 2
    @Dzamo Norton - Are you able to capture and publish the reference to the commit from what your compiled artefact is derived within your deployed artefact? E.g. a version in a footer, an endpoint that publishes the version, or statement in the logs. I'm suggesting querying your actual deployment vs book keeping in a git branch. As AyexeM pointed out, if the deployment process breaks down master will no longer be an accurate reflection of what is deployed.
    – Jim V
    Commented Nov 13, 2020 at 1:15

6 Answers 6

77

It comes from the CI mindset where there is integration several times a day.

There are pros and cons of both.

On our team we have abandoned the develop branch as well since we felt it provided no additional benefit but a few drawbacks. We have configured our CI software(Teamcity) to compensate for the drawbacks:

  1. Enable deployment of a specific commit. In other words: We don't deploy a branch. We deploy a commit.
  2. We can deploy either master or branches starting with a hotfix/ prefix.

The reason this works is because all pull request contain potentially releasable code but this doesn't mean we deploy all commits in master.

The main reason we abandoned the develop branch is because it tended to get too large and too time consuming to see what it actually contained. If we have deployed something a little prematurely we just branch off a hotfix branch and deploy that directly.

4
  • 25
    Having worked with a develop branch for a year or two, just to have it merged into master every now and then, I can just say: amen, abandon that thing :]
    – stijn
    Commented Mar 7, 2016 at 21:06
  • 1
    Interesting. So I assume when you release version 1.3 for example, you tag a specific commit on master, so you if a bug arises later while master is in a state of flux, you can easily branch a hotfix off of the 1.3 tag?
    – ffxsam
    Commented Mar 7, 2016 at 22:06
  • 9
    I'd say the benefit of "develop" depends heavily on what kind of software you're making, how it's deployed, and whether you need to support multiple live versions or not.
    – axl
    Commented Mar 8, 2016 at 0:30
  • 3
    @ffxsam we don't even need tagging because we are tracking which git id is currently deployed. This is logged in both TeamCity and branched into deployed dll's and in azure management portal. So we have not felt the need for further tagging except from the automatic tagging done by TeamCity. If you feel tagging fits you work flow better it would also solve it nicely. But yes, in principle branch off directly from the currently deployed change to make a hotfix branch. Commented Mar 8, 2016 at 7:05
37

There are two philosophies I've seen in projects, and I think the choice is just a matter of taste:

  1. Designate 'master' as the production release and develop in a 'develop' branch.

  2. Develop in 'master' and have a differently-named branch for stable production releases. This makes even more sense if your project has multiple release branches at a time (e.g., the current preferred one is Release-1.8, but you also are still maintaining Release-1.7).

Both are common approaches, and have their pros and cons.

3
  • 3
    I agree with you. We prefer to have release branches and maintain those around until the next release to production. If we have to make any hot-fixes, we checkout the last release branch and work on that, then merge those hot-fixes into master/develop branch
    – Johnny
    Commented Aug 30, 2018 at 18:27
  • Exactly. What 'master' should do is mostly semantics. The fundamental thing to get right is avoiding having to keep multiple forever-living branches bi-directionally sync'd unless you have a really good reason to do so. The 'master' branch in Git Flow is just a lagged replica of 'develop', so it doesn't really count. The anti-pattern is allowing the main development branch to hold changes that never go into a release, which is a shockingly common practice I've seen. Both models mentioned above prevent this, which is why they work. Commented Mar 26, 2019 at 21:29
  • For those curious, have different branches for releases is commonly called "Release Isolation", and is a great thing. I'm personally a fan. Microsoft also has recommendations for it as well: docs.microsoft.com/en-us/azure/devops/repos/git/… Commented Nov 30, 2021 at 20:00
32

A develop branch matters more if your process to release is complex and you need to have serious release-candidates.

For example, imagine you are writing software which is firmware on cars. This is... non-trivial to fix and it is likely any release would have a comprehensive set of non-CI/integration tests run on real hardware.

In that case it may make more sense to isolate a "release candidate" in a non-master branch (such as "develop"). That allows your team running those tests to have a branch to merge features into.

Webapps or other easily updated software do not have this constraint.

However, note that:

  • Many (most?) projects on github do not have this sort of constraint
  • A main "master" serves the same purpose
  • A workflow of "make a PR vs master" is far more universal than "make a PR against a branch that you don't know immediately on this repo"
1
  • 2
    Isn't this resolved by just using tags? Instead of always using the head of master, you would deploy the commit tagged with the latest version (either a static v x.x.x tag and/or a latest tag that you move to the most recent "approved" commit on master). This is basically how package managers work.
    – booshong
    Commented Sep 4, 2020 at 1:00
15

If developers are working on feature branches, and then merging those into master when they're done, that means there's a period of time where features/fixes are being merged into master and the master branch is actually newer than production.

...

Imagine if people are merging straight into master, and a bug is reported in production that becomes difficult to fix because the master branch codebase has changed significantly.

That's not Github Flow.

This is the Github Flow deploy/merge process, according to your link:

Deploy

Once your pull request has been reviewed and the branch passes your tests, you can deploy your changes to verify them in production. If your branch causes issues, you can roll it back by deploying the existing master into production.

Merge

Now that your changes have been verified in production, it is time to merge your code into the master branch.

(Emphasis mine)

In other words, master will never be ahead of production. Similarly, master will always be in a stable, releasable state (aside from undiscovered bugs), since everything is reviewed, tested, and rolled out to production before being merged to master.

5
  • 1
    Nice! This makes great intuitive sense - master is always your rollback position if the feature branch you push into production fails. If it doesn't, it gets merged into master and becomes the new fallback. I like it. Commented Jul 12, 2019 at 19:06
  • 3
    I've always merged into master before pushing into production, which after reading this I'm realizing that's a mistake. Commented Nov 9, 2019 at 4:23
  • This always confused me about git/hub flow. Which comes first? The merge commit on master or the release? Releasing (a release branch) and then any type of merge (merge commit, squash commit) on master means the commit on master is different from the commit that was actually released. Rebase merge is a different issue, in that there may be commits on master that aren’t in your release branch, and are then not included in your release, but rebased over on master. Without a great deal of attention to your merge, it’s difficult to say that exactly what you released is represented by master.
    – rjminchuk
    Commented Jan 3, 2021 at 19:38
  • 2
    @rjminchuk All merges to master should be doable as fast-forward merges, meaning master ends up with the exact same commit as was released. You can optionally force a non-fast-forward merge, to create a marker commit, but the diff between the merge commit and the released commit should be empty. If the diff is non-empty, then that implies that you've got multiple versions released simultaneously and/or your releases are randomly dropping features. Either way, I'd think something has gone seriously wrong, or Github Flow is not suitable for your needs.
    – 8bittree
    Commented Jan 4, 2021 at 18:48
  • I’m pretty sure the primary git providers out there all allow you to force fast-forward merges on your MR/PR’s as well. Thanks for the clarity @8bittree! I think it’s important to mention in GitHub flow that without fast-forward merges only, you must adopt another form of release versioning like long lived release branches, or tagging. I prefer Trunk based development and tagging :)
    – rjminchuk
    Commented Jan 5, 2021 at 19:58
10

Releases to production can be tagged, so the situation that was released can always be reproduced without devoting an entire branch for this purpose.

If a critical bug is found in production at a moment when master can't be released, then it is easy enough to checkout the tag and start a new "hotfixes-for-release-1.2.0" branch from there. But that should be rather rare.

Most of the time in our web applications, master has changed since the last release but not very significantly, so we can simply do a new release from master that has the fix. It helps to do very frequent releases anyway.

5

The issue I see is that Git/Hub flow deploy/merge assumes one feature is being developed/tested/merged/deployed at a time - and often in my experience this isn't the case. If we merged a feature at a time, there is a larger chance for regression issues - only found after the features are merged to master and possibly in production.

There needs to be a way to test multiple features, merge multiple features and deploy the same. I've been using a 'bundle branch' (a branch created from master with test ready feature branches merged into it) that gets deployed to qa/uat. Corrections during uat happen on the feature branch only, and those get re-merged to the bundle branch. After a subsection of the bundle branch is approved, only those approved features within the bundle get pull-requested to master - and the cycle is continuous.

I use this with Gitflow, but pondering to use it for GitHub flow. The QA/UAT many feature at a time issue seems of significance. Another issue with GitHub flow is it assumes all sr developers, and that is not always the case.

I would rather use the GitHub flow due to its simplified-ness. With a bundle like feature, I think it would be better ready. I'ts possible the bundle is similar to release; however, I am still pondering this as well.

Another issue is the pull request process happens at the end before merging to master; however, sometimes you want to code review prior to the business qa testing - hence well before the merge

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