I tried using Gitflow on our team, but there was too much complexity for me. We ended up switching to Trunk Based Development (TBD)[1] which I and my team found to be much simpler.
I would love all the hours back I spent in discussions around branching strategy, trying to keep complex models understood across the team (and myself), dealing with painful merges and flowing changes through, trying to figure out if a change is in a branch already, etc..
It's so much simpler and more productive if everyone works in master, with new features behind a flag if need be, with just critical fixes ported to release branches.
There will always be arguments for why a more complicated branch strategy needs to be introduced. Resist those arguments. In my experience, the cost rarely pays for any benefits. Writing good software is hard enough already.
Same here. Trunk based is easy to explain and enforce.
The only challenge we faced was maintaining patch releases. Folding in fixes for common issues which were found in newer releases sometimes involved more than just cherrypicking the fix into a patch release for an older version.
This inevitably led to asking users to update to more up-to-date versions. This further enforced the linear development paradigm.
+1 to trunk based. There's obviously a lot there, but one of the best bits is the idea that each release deserves a branch. It makes hotfixes, ci/cd, and rollbacks all much simpler to reason about.
TBD is fine for web apps, but not for software that you have to maintain multiple versions in the wild at the same time or when the release cycle takes several weeks.
The thing I don't get about trunk-based development is: if everybody always pushes straight to master, how do you do code review? Or don't you do code review in TBD?
I like having explicit pull requests where a new feature can be reviewed.
Reading the comments, I realize I'm a git neophyte (limited experience working on some open source software, didn't know "gitflow" was a thing) so excuse me for my naive question. But what about this simple workflow. Developers submit PR on top of a master branch (developer is in charge of rebasing, PR must pass integration test). Administrator is in charge of merging, maintains a linear history. Releases are just tags on master. Has this workflow a name? anything wrong with it?
A year after you release v1.0.0 (which you say is a tag), a customer reports a bug in it. They don't want a breaking upgrade to v9.13.0. They want to pay for v1.0.1 (aka "hotfix").
But you can't open a PR against a tag v1.0.0. Hence you discover that v1.0 should be a branch, and both v1.0.0 and v1.0.1 tags. This way you can open a PR against v1.0 and easily create v1.0.1, v1.0.2, etc.
Another problem.
You are at "master" and approach v13.0.0. But there are numerous bugs to fix before you release. Testing takes >24 hours. You choose to work on bugs on a branch (v13.0) this way master can proceed with new features and not be feature-frozen for days or weeks.
Another problem.
Your CI is deficient in that it allows merging and cloning before it makes sure that previous merge produced good product. Puny as it is, it is the current industry standard. Thus your main branch becomes broken now and then. So you call it "develop" and only merge it to "master" what you are sure is a good product.
If these common situations don't apply to you - proceed as you are. Do the simplest thing possible, but not simpler. What you've described doesn't create any roadblock or dead end street for the project.
As others have stated, this works well when there aren't "releases" but once you have releases with versions and may have to backport things, it starts to breakdown. For how most web-based software is developed it seems to be a descent for.
It will work fine 99% of the time. But when you get into trouble (and a single merge done badly may cause trouble) there is no way to recover it because you lost history. And trouble is often of the form, "A month of my work went poof and nobody noticed for weeks after."
Another pain point is that the Administrator becomes a bottleneck. And when the Administrator runs into a conflict they often have no context from which to sort it out.
But on the positive side, your history will be nice and linear. Which makes tools like git-bisect very, very happy.
It may be different if you develop something which is a library (rather than app) AND it is big enough you consider backporting changes to older versions.
If you don't, release branches (rather than tags) are nothing by a burden.
the risk of this workflow is that PRs will languish for too long, and the work required to rebase them when they're actually needed will cause friction and mistakes. this will often manifest when your software reaches a certain level of maturity and you have established a release model that distinguishes between a release that includes only bugfixes and a release that introduces new features.
you definitely want to get your PRs merged in to _something_ as soon as they are complete, to avoid bitrot. but just because they're complete doesn't mean you want them included in the next release.
Kind of, that article recommends making things less complex if you do continuous delivery to a SaaS.
The update article mentions it was meant for versioned software.
I tried to articulate the various levels of branching you need in GitLab Flow https://docs.gitlab.com/ee/topics/gitlab_flow.html The various levels are: feature branches, production branches, environment branches, and release branches.
We started with gitflow, but our team ended up going with a Release based branching system as the constant integration of various features ended up giving less control on what to deploy and when. Most common scenario...
Devs create feature branches from master
Features will be targeted to a release at some point, Release branch gets taken from master
Devs PR feature branches to the release branch
Release branch merges back to master on deployment.
A problem with GitFlow is it's painful to follow PR model.
Especially on the Github repository where pushing to master is a lock and can only done by PR and merge(or squash or whatever).
Let's take a look at a release:
1. Branch of release/1.0 from develop
2. Fix some bug, then at the time of deploymennt. Merge it back to master and develop
But once we merge, github close the PR... If we attempt to create another PR for other branch. The Github now see different history between master/develop...
I've yet to work on a codebase that was so congested it required such strong delineation between feature/hotfix/release but I can see how it might be required at a certain size. I wonder what that threshold is.
It depends what you're working on. We have a fairly small team (7 engineers) working on a reasonably complex app (many features).
Our "features" take anything from 1 day to 3 weeks of effort, and generally need to roll out as a whole. They are often really upgrades of existing features, and the work to continuously merge w/ feature flags, supporting both flows/designs, is just not something we've felt was worth the extra time.
We release on a 2 week cycle, the same day each time. We merge our features into the develop branch as they are ready and safe for production.
Our scheduled release day is Wednesday. The Thursday beforehand, we branch from develop into a release/x.y.0. This builds release candidates. We have a sanity check on Friday, then our remote QA team runs through them over the weekend. Any issues they find, we try to have squared away by Monday, Tuesday at the latest.
Meanwhile other team members are still merging new things into develop. It's useful to have that release branch because it lets the rest of the team keep moving - we maybe only put out 1 or 2 developer's features each cycle, the rest are still trickling in.
Once we release, we tag, merge into master, and start over again. If any issues show up on production, we use the hotfix branch, hotfix/x.y.z. That let's us resolve issues with risking a ship of any of the changes that have come into develop that haven't had a few days of stability behind it.
For our team scale, we have a lot of users (100k's DAU), and we find this method is a nice balance between the pace of output you might get from true CI but with the reliability of a more traditional cycle.
Backend and web projects, however... Straight CI, into master, and we roll out test > staging > production when we're happy.
It all depends on the situation. The simplest possible situation of mostly just having a master branch also can work quite well. When you have specialized testers that test a candidate release you start to need release branches. Feature branches start being necessary if changes are temoprarily incompatible with current master. This should not be too common, though. In many cases one can avoid feature branches by having feature switches that get removed as soon as a feature is done. If one wants to or needs to use feature branches they should be short-lived because one will be creating a merge hell if this is not the case. The git flow seems just too complicated for most cases. One comment already notices that it is quite unclear why a separate development and master branch are necessary.
I love this branching model. I have being used in all projects and teams I can. I use it even in projects where I work alone. For me it is the ultimate branching model.
AFAICT Gitflow just has one more branch than it needs. If you got rid of the master branch and supported production releases off release branches it would be just as useful and significantly less complicated.
Can anyone explain to me what real value the master branch adds in this model? And without using fluffy meaningless words like, "source of truth," please.
I have never succeeded in working in a branch and having the real owners accept my state.
I am of course talking about 'outsider' changes to code, but the effect is real: the master owner can elect to say "sorry, we decided to re-architect significantly and what you did is now superfluous, or at least too hard for us to re-integrate" and almost everything I have been involved with, this is what happened.
Submitting small patches to their head state is more effective for me than trying to maintain state against a moving target with a realistic chance of making significant change, and having it accepted into the mainline.
Strongly agreed with the new author note. I used the same ideas with the teams I've been coaching:
"Consider your context...." as the need or not of support for multiple versions and "...Decide for yourself.
History is for reading, not writing. Do we make decisions that give us readable and informative histories? The people who give up and rebase absolutely everything into one linear trunk are not working optimally, but at least they're trying.
So cool that something Linus Torvalds made to solve his own problems, spread all around the world so quickly. I guess great dev tools can only be made by great developers, who have been through a lot of scenarios/problems themselves.
What's interesting to me is that git does not seem like a "great dev tool" when you first start using it, especially if you're already used to another VCS. Right now I'm using SVN, Perforce and git for different projects and I definitely like git the most, but it took a while to get there. And it's not the centralized vs. decentralized per se, like 99.9% of git users I'm almost always within milliseconds of a central server. The big change was to treat my development "as-if" I was doing my own thing, decentralized, when in fact I'm not.
[+] [-] umvi|6 years ago|reply
[1] https://trunkbaseddevelopment.com/
[+] [-] billti|6 years ago|reply
It's so much simpler and more productive if everyone works in master, with new features behind a flag if need be, with just critical fixes ported to release branches.
There will always be arguments for why a more complicated branch strategy needs to be introduced. Resist those arguments. In my experience, the cost rarely pays for any benefits. Writing good software is hard enough already.
[+] [-] Legion|6 years ago|reply
[+] [-] zoomablemind|6 years ago|reply
The only challenge we faced was maintaining patch releases. Folding in fixes for common issues which were found in newer releases sometimes involved more than just cherrypicking the fix into a patch release for an older version.
This inevitably led to asking users to update to more up-to-date versions. This further enforced the linear development paradigm.
[+] [-] wcarss|6 years ago|reply
[+] [-] bosswipe|6 years ago|reply
[+] [-] alexbanks|6 years ago|reply
[+] [-] jpswade|6 years ago|reply
Trunk based development gives you that. No long lived branches. No merge hell.
It’s considerably better.
[+] [-] mcv|6 years ago|reply
I like having explicit pull requests where a new feature can be reviewed.
[+] [-] yodsanklai|6 years ago|reply
[+] [-] kubanczyk|6 years ago|reply
But you can't open a PR against a tag v1.0.0. Hence you discover that v1.0 should be a branch, and both v1.0.0 and v1.0.1 tags. This way you can open a PR against v1.0 and easily create v1.0.1, v1.0.2, etc.
Another problem. You are at "master" and approach v13.0.0. But there are numerous bugs to fix before you release. Testing takes >24 hours. You choose to work on bugs on a branch (v13.0) this way master can proceed with new features and not be feature-frozen for days or weeks.
Another problem. Your CI is deficient in that it allows merging and cloning before it makes sure that previous merge produced good product. Puny as it is, it is the current industry standard. Thus your main branch becomes broken now and then. So you call it "develop" and only merge it to "master" what you are sure is a good product.
If these common situations don't apply to you - proceed as you are. Do the simplest thing possible, but not simpler. What you've described doesn't create any roadblock or dead end street for the project.
[+] [-] SideburnsOfDoom|6 years ago|reply
[+] [-] deepersprout|6 years ago|reply
[+] [-] mugsie|6 years ago|reply
It is fine, unless you do a lot of back ports or bug fixes for older releases, at which point the version branches are very useful.
[+] [-] jimktrains2|6 years ago|reply
As others have stated, this works well when there aren't "releases" but once you have releases with versions and may have to backport things, it starts to breakdown. For how most web-based software is developed it seems to be a descent for.
[+] [-] btilly|6 years ago|reply
It will work fine 99% of the time. But when you get into trouble (and a single merge done badly may cause trouble) there is no way to recover it because you lost history. And trouble is often of the form, "A month of my work went poof and nobody noticed for weeks after."
Another pain point is that the Administrator becomes a bottleneck. And when the Administrator runs into a conflict they often have no context from which to sort it out.
But on the positive side, your history will be nice and linear. Which makes tools like git-bisect very, very happy.
[+] [-] stared|6 years ago|reply
It may be different if you develop something which is a library (rather than app) AND it is big enough you consider backporting changes to older versions.
If you don't, release branches (rather than tags) are nothing by a burden.
[+] [-] snarfy|6 years ago|reply
[+] [-] woodrowbarlow|6 years ago|reply
you definitely want to get your PRs merged in to _something_ as soon as they are complete, to avoid bitrot. but just because they're complete doesn't mean you want them included in the next release.
[+] [-] ulisesrmzroche|6 years ago|reply
[+] [-] gulbrandr|6 years ago|reply
[1] https://news.ycombinator.com/item?id=22485489
[+] [-] sytse|6 years ago|reply
The update article mentions it was meant for versioned software.
I tried to articulate the various levels of branching you need in GitLab Flow https://docs.gitlab.com/ee/topics/gitlab_flow.html The various levels are: feature branches, production branches, environment branches, and release branches.
[+] [-] unknown|6 years ago|reply
[deleted]
[+] [-] keithnz|6 years ago|reply
Devs create feature branches from master
Features will be targeted to a release at some point, Release branch gets taken from master
Devs PR feature branches to the release branch
Release branch merges back to master on deployment.
[+] [-] kureikain|6 years ago|reply
Especially on the Github repository where pushing to master is a lock and can only done by PR and merge(or squash or whatever).
Let's take a look at a release:
1. Branch of release/1.0 from develop 2. Fix some bug, then at the time of deploymennt. Merge it back to master and develop
But once we merge, github close the PR... If we attempt to create another PR for other branch. The Github now see different history between master/develop...
[+] [-] debaserab2|6 years ago|reply
[+] [-] stickydink|6 years ago|reply
Our "features" take anything from 1 day to 3 weeks of effort, and generally need to roll out as a whole. They are often really upgrades of existing features, and the work to continuously merge w/ feature flags, supporting both flows/designs, is just not something we've felt was worth the extra time.
We release on a 2 week cycle, the same day each time. We merge our features into the develop branch as they are ready and safe for production.
Our scheduled release day is Wednesday. The Thursday beforehand, we branch from develop into a release/x.y.0. This builds release candidates. We have a sanity check on Friday, then our remote QA team runs through them over the weekend. Any issues they find, we try to have squared away by Monday, Tuesday at the latest.
Meanwhile other team members are still merging new things into develop. It's useful to have that release branch because it lets the rest of the team keep moving - we maybe only put out 1 or 2 developer's features each cycle, the rest are still trickling in.
Once we release, we tag, merge into master, and start over again. If any issues show up on production, we use the hotfix branch, hotfix/x.y.z. That let's us resolve issues with risking a ship of any of the changes that have come into develop that haven't had a few days of stability behind it.
For our team scale, we have a lot of users (100k's DAU), and we find this method is a nice balance between the pace of output you might get from true CI but with the reliability of a more traditional cycle.
Backend and web projects, however... Straight CI, into master, and we roll out test > staging > production when we're happy.
[+] [-] cjfd|6 years ago|reply
[+] [-] edpichler|6 years ago|reply
[+] [-] arghskwidge|6 years ago|reply
[+] [-] ggm|6 years ago|reply
I am of course talking about 'outsider' changes to code, but the effect is real: the master owner can elect to say "sorry, we decided to re-architect significantly and what you did is now superfluous, or at least too hard for us to re-integrate" and almost everything I have been involved with, this is what happened.
Submitting small patches to their head state is more effective for me than trying to maintain state against a moving target with a realistic chance of making significant change, and having it accepted into the mainline.
[+] [-] nilsandrey|6 years ago|reply
[+] [-] unknown|6 years ago|reply
[deleted]
[+] [-] juped|6 years ago|reply
History is for reading, not writing. Do we make decisions that give us readable and informative histories? The people who give up and rebase absolutely everything into one linear trunk are not working optimally, but at least they're trying.
[+] [-] mkchoi212|6 years ago|reply
[+] [-] zwieback|6 years ago|reply
[+] [-] bmn__|6 years ago|reply