"A source-control branching model, where developers collaborate on code in a single branch called ‘trunk’, resist any pressure to create other long-lived development branches by employing documented techniques. They therefore avoid merge hell, do not break the build, and live happily ever after."
In my experience, new/small teams do well if they stick the "Scaled Trunk-Based Development" model until a legitimate reason to deviate is discovered (e.g. needing to back-port changes to an older release may imply making commits to non-trunk/master branches...).
It's of course possible to have a meaningful discussion about different types of branches, releases, changes and about what changes should be merged, when, and where, but ultimately there is only one good branching strategy: thinking.
Thinking about the purpose of branches, thinking about whether everybody is on the same page and what mistakes are possible, thinking about useful rules about changes and merging (possibly on a branch by branch basis), thinking about when to break and how to adapt the rules, and above all thinking about the objective of making correct and low-effort merges.
Adopting practices because a blog post says so is the opposite of maturity. As Gitflow is presumably a good fit for the project it originated in, any "alternative styles" are suitable for someone else's particular needs and should be treated as examples and anecdotes illustrating general principles.
I default to recommending either Github Flow[0] or Gitlab Flow[1] these days.
Both of these models simplify Gitflow by dispensing with the long-lived development branch and therefore the complication of needing separate hotfix vs release workflows.
The difference between these models is that Github Flow expects you to deploy to environments within a pull request before merging to master, whilst Gitlab Flow expects you to merge to long-lived environment branches for deployment (presumably using Gitlab's CI features).
"Any branching model you choose is ultimately meant to make humans work together more easily to produce software"
There are things in this article I agree with, and things that I don't, but the quoted point is something that I wish could be universally understood. Some developers commit to the dogma of one blog post or another and forget about the fact that the whole thing is for the _people_ who are writing the code. Branching strategy should help to optimize workflows and minimize friction, regardless of how badly bastardized your approach is vs. its source material.
I can't seem to get people to agree on the point of unit tests either.
Nowhere is this more apparent than when we argue about test coverage %'s. There's a whole bimodal distribution of people very wrong for very different reasons.
I feel unit tests are difficult to swallow to some people because they are not used to (or able to) develop code in distinct and definite units. And without units, unit tests are sort of meaningless.
I find about half the people don't see the point (mainly can't be bothered). I can cut that group by about a third by telling them "the tests keep other people from breaking your code"
(Personally I think tests keep me from breaking my and others' code, but I don't tell them that)
For me, it’s frustrating to see people make in-depth, well-considered points about why something is problematic, and have that be met with “well you just need to pick the right tool for the job guys!” It’s such an anodyne and vacuous point to make, precisely because the whole dialog is around whether and when a tool is the right one.
Given a job, people will disagree about what the correct tool is. Given a tool people will disagree about what jobs it’s good for. There is no way around this, and there are times when a decision must be made.
I used a watered down version of gitflow on a project with heavy customer involvement.
Instead of doing the whole thing, we had feature branches (which I still hate), master, and one more branch for the stuff we were showing to the customer. Who sometimes would decide they didn't like what they asked for and please don't push this to production.
With the exception of hotfixes, master was always just a certain number of commits behind the working branch.
Very aggressive use of dark launching of features could also solve this problem, but we've had our share of problems with that strategy too (Sprint-obsessed thinking makes it difficult to go back and clear out old conditionals once they've settled)
Most obviously, the boundaries of source code repositories should be aligned with released modules: if "the system becomes a manifest of the different revisions of the different repositories" the repositories are too fragmented (or the releases too monolithic), if "teams are independent and microservices should be independently deployable" disparate components should not share a monorepo, and in both cases the difficulties are consequences of bad architectural choices, not of branching models.
git flow never made sense for me. Because of the complexity some devs would always mess things up or ignore the branching altogether. Merging all the related branches into master when doing a release took multiple days and often introduced subtle bugs.
Switched at some point to GitHub flow and never looked back.
I've have 400+ devs acoss several states working with 25+ repos, all using a modified Gitflow.
It took a month of negotiation to get buy in, so far, it's been working for the last 2 and a half years.
And the beauty is, if a team wants to be more "agile"/more continuous, all we have to do is kill a few branches, and start building/releasing directly from master.
> Merging all the related branches into master when doing a release ...
--- doesn't sound like Gitflow. In Gitflow, the topic branches have been merged into the develop branch first, as they were finished. In contrast, merging into master is a merge from a single branch. You branch from develop into a release branch. Then you merge the release branch into master.
What if you have multiple ongoing release (maintenance) branches whose changes should all be merged to master and develop? It quickly becomes messy (but to be fair so does most alternatives).
There's nothing wrong with gitflow... The problem comes with how it's managed. The problem comes when a risk-averse manager wants to follow a 1990s release cycle, and release and feature branches live forever.
Release branches should be created shortly before release, and shouldn't deviate too much from develop. Feature branches also shouldn't last very long.
If a feature is going to be under very heavy development before shipping, a better strategy is to #ifdef the feature. This helps avoid accumulating merge conflicts that happen when there are long lived branches.
In real world software dev, I fail to see how a release branch is a flaw. It’s completely reasonable to want to test something in a “gold-master” state before shipping it to prod. Regardless of how many tests you have, that’s just a good idea.
Yeah it's what we call staging. I have a project now that doesn't have a staging environment that's well integrated and it's very nerve-racking. I use hg but it's the same idea.
That’s what versión tags are for. Plus real world software development, what does that mean? Just say it straight up: you don’t think I have a real job
No, that's not what I meant and I apologize if it came across that way. What I meant was, it's easy to think of an idealized world where a everything has test suites with 100% branch coverage, complete e2e tests, automated screenshot tests of the UI, etc. But, in the real world, that most often isn't true. I've been on a lot of teams. Lots of legacy code has no automated tests at all. Lots of modern code has decent unit test coverage, but nothing for the UI.
These are cases necessitating a manual testing step before releasing to prod, and manual testing will often uncover bugs that need fixed. Thus, you need to be able to fix these and continue testing, all the while having as little impact as possible on other Devs working on things unrelated to this release.
Having either a single long-lived release/QA branch or shorter-lived release-specific branches accomplishes this in a reasonably simple way.
That's what I meant by real-world software development. If you work at a shop with an amazing test suite and don't need these steps, good for you. But, in my 15 years of development, I've never seen a shop like that.
Speaking for myself, git flow is intuitive. It is something you also have to practice discipline to adhere to. That is not simply "additional cognitive load", it is just like any other process worth following.
Their criticism about "tripling the number of merge conflicts" because of the number of branches doesn't make any sense. As long as developers are doing development work and committing, regardless of what branch they're committing to, there is potential for conflict. It might not be a "merge" conflict in the sense of two separate branches, but it will manifest as a merge conflict in pushing the local to the remote. The potential for conflicts stay the same. What git flow gets right here is it isolates logical workflows from each other, so people working can work for as long as necessary without conflict.
>Gitflow abandons rebasing
Rebasing is a nightmare for distributed work, and in my opinion, only makes sense in limited circumstances where your code is not already pushed and pulled in multiple locations.
>Continuous delivery is a practice where the team release directly into production with each “check-in” (in reality, a merge to master), in an automated fashion. Look at the mess that is gitflow and explain to me how you’re going to be able to continuously deliver that?
Every modern CI/CD framework can run automated jobs after a merge into master, so I'm not sure what the criticism here is?
>Have you ever tried a complex branching model like gitflow with multiple teams, and hoped for everyone to be on the same page? Can’t happen.
That is less a criticism of git flow and more a criticism of any software organization that tries to have repeatable deployments with many services. It's a difficult problem in general, and not one that git flow is attempting to solve in the first place. You will have that problem regardless of if you use git flow or not.
I could go on but there's a lot here. It sounds like the author is very frustrated and annoyed with git flow, and perhaps is used to cowboying code (the desire for frequent rebasing give me a hint to this) without regard for the impact on other developers. I've worked with people like this, and they often provide no alternative solutions, just frustration and resistance to following an imperfect process. It's a rant without much substance.
> Every modern CI/CD framework can run automated jobs after a merge into master, so I'm not sure what the criticism here is?
The criticism (and the one thing I can sort of agree on) is that with git flow you are not merging to "master" on a continuous basis. Select quotes from the nvie post describing gitflow:
> When the source code in the develop branch reaches a stable point and is ready to be released, all of the changes should be merged back into master somehow and then tagged with a release number
> The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release)
> By doing all of this work [release prep] on a release branch, the develop branch is cleared to receive features for the next big release.
> Have you ever tried a complex branching model like gitflow with multiple teams, and hoped for everyone to be on the same page?
My company does exactly this and I am happy to report there have been no issues. I think the key reason we don't have issues is we are strict about maintaining backwards compatibility between services and also try to maintain forwards compatibility where possible.
> “What’s in production” becomes an existential question, if you’re not careful.
We solved this by embedding the SHA's of a build's constituent repos in the build artifact.
One would think by simply looking at the picture that gitflow is not well suited for processes that do not involve distinct releases. In other news, SaaS is not the only model in the world and CD is not always possible.
This is pretty much exactly what we do, except add in a third “qa” branch between dev and master, for the purpose of manual testing before things go to prod.
This is where GitFlow makes sense - when you have a QA and/or enduser acceptance process before code is committed to a master/release branch.
Also for DevOps you sometimes need to be able to branch off Master to apply a critical patch which then gets merged back into Dev later. You don't want to ever need to do that, but if subverting the normal process makes sense because you have all signoff parties gathered at the table - you do what needs to be done.
Indeed. i have been using Gitflow for the last 4 years on more than 14 repositories with teams spanning from 2 to 30 commiters and it worked. I honestly do not see what is the problem with having the code running on production on master, develop harboring the code deployed on review branch, and release/tags branches deployed on QA environment. Moreover each team can adapt the model to it's own workflow...
This still sounds like an anti-pattern to me, at least in a typical web app. I’ve seen a very similar workflow used in a previous org, and the main benefit was that it limits the number of times you have to cross your fingers and hope for the best (which is obviously masking other reliability problems). Merging each feature branch wasn’t scary because it wasn’t going to deploy yet, but that means it incentivizes somewhat of a “not my problem” culture. Then at some point someone builds up the courage to merge the develop branch to master and you hope for the best. Repeat every few days.
There was also some wishful thinking about doing more qa testing than anyone actually did. The develop branch would immediately deploy to the staging environment, so someone might have tested new features there before they ship to production. But if there’s no rigorous process around exactly what needs to be QA’d and whose responsibility it is, then let’s be realistic, it’s not gonna happen.
The downsides are that release times were less predictable, deploys were bigger which means potentially more difficult to trace down bugs that do show up and roll back when needed, and things would get delayed for no reason. Oops, I thought I shipped that thing for marketing a few days ago but nobody deployed the develop branch since then.
Developing small features right into develop sounds like a bit of an issue on its own too. Seems like you’re not quite confident enough to deploy it right away, but it’s also presumably circumventing the regular code review process so it’s not going to get reviewed.
The only reason I can see for why these downsides would be worth it, is if you have some hard constraint that you can’t deploy very frequently (for instance releasing a downloadable desktop app or mobile app), and/or you have a formal, rigorous manual QA process when merging from develop to master.
I don’t get it. I manage multiple teams that are doing web apps. Many of those use Gitflow like life cycles and none of them has issues based on their lifecycle. Some of them do release branches, some not. Some do ff-only other don’t. Doesn’t really matter as long as it is efficient (simple) enough. Of course we are also not only deploying the long lived branches but actually every push results in some sort of ephemeral environment being spun up tested and spun down again (or stick around in car of failures) so Feedback on what is happening is quite direct but any way. If you help teams find a pragmatic lifecycle for them you can avoid all the perceived issues of any cv lifecycle.
One exception might be the occasional group of optimists trying their hand at micro repos. These are just bound to blow up :-D unnecessary conplexity and all...
In my experience, an additional gap between working directly on master is many teams don't understand the concept of promoting builds. So e.g. you can build on every commit, then _after the fact_ promote one to an actual release (without re-building). This isn't suitable for _every_ situation, but it is for all the ones I've encountered so far.
Relatedly is "release branches". An alternative is to simply tag the release that went out, which is the same thing. If it needs a hotfix, you branch off the tag, fix it there, then apply that fix (cherry-pick or redo) back to master.
Overall, IME the biggest benefit is the cultural changes it instills in the team: Everything must be good enough to release, and everything goes to the same place. For projects that can afford it (again, most can I bet) its a huge drop in mental effort to understand the state of the world at any given time.
Unsure how, but I've only had to work in small teams to relatively low complexity. Can you explain your use case for multiple development branches in the sense that I describe (just a combined endpoint for all merged features that have not yet been deployed).
We use this pattern in a monorepo and it works great. Master is a reliable history of releases, and Dev is a reliable place to start your feature branch. Yes, someone has to own the decision about when and how to thoroughly integration test Dev before release, and do so often. But for 100 other reasons, this judgement call is necessary anyway.
I don't mean that as a problem, just that that's what I would do if I did it that way (and I don't see it as a problem, just the concomitant requirement for changing).
> * major features are done in feature branches, w/rebasing prior to merge
Rebase in a feature branch, that can be long-lived and have many commits, seems like a painful experience to me.
You can end up solving the same conflict more than once, or even solving conflicts that don't exist in the final result.
no-ff merge commits are usually easier to solve.
Am I missing something? Is there an easier rebase strategy?
Same. I think people just have different ideas of what "long lived" means. To some it might be a few days of work, to some weeks.
We actually merge the master into our long lived feature branches first. Then run all the tests on that branch, if it's good it can be directly merged into master (master is locked, and you need permission to commit anything to it).
I think so. Sometimes we have long-lived branches with multiple contributors for new features. Is this some kind of anti-pattern?
We don't use feature flags, they seem hard to maintain and restrictive in terms of what you can do (e.g. structural changes).
OTOH, because we're a small team, when there's a lot of work in a new feature branch there's little work on master, so there's little hassle there too.
Sometimes it's painful, normally it's not, and yes - the longer lived it is the more painful it's likely to be.
no-ff merges are easier, but leave a messier non-sequential history of when things actually go out which is sometimes confusing when understanding why things are the way they are; I generally, but not always, judge it to be worth the pain!
I think gitflow might be suited to mature product work where development is ongoing.
It keeps coming up in my consultancy work, usually on short term projects that either die or generally just get left to tick over where it's wildly unsuitable. Mostly because of the way it violates that principle of short lived branches.
It seems to me that most of the authors objections stem from 100% strict adherence to git flow, which IMO is the wrong approach.
I loved the concept of git flow when I first read that legendary blog post. I learned a lot and adapted it into my own development workflow. I've bounced back and forth over the years in how strictly I adhered to the One True Way (tm) based on how well it worked for me in actual projects.
IME I think the best approach to git flow is to learn and understand it and then adapt it to your project's workflow, as opposed to strictly adhering to every tenet of git flow. I have multiple projects using different "amounts" of git flow - e.g. a large project with dev, qa, hotfix and release branches vs a small personal project with only master and dev.
> 100% strict adherence to git flow, which IMO is the wrong approach.
I agree, as with most things, there certainly is room for flexibility here.
One problem I've seen repeatedly occur when migrating to git flow is a misconceptions about 'bugfix/' branches, which are intended to be used when stabilizing a 'release/' branch. However devs use that prefix for every bug they find which is not related to a story/feature. And to be honest, they are right to do so. The naming is just bad here, since the term 'bugfix' is so generically used, it's not very intuitive to use it only for release branches. So I've come to the point where I would agree to use 'bugfix/' for regular bugfixing if the team/company is comfortable with it, even though it is opposed to original gitflow.
I agree 100%. I too tried Gitflow on many different projects, with different skill levels of teams and we ended up pulling the plug on it and going back to "master is always deployable/production". Developers work in feature branches that are small and atomic, with frequent merges into master with corresponding deployments. Breaking master is a critical blocker issue. There's no need for tags, complicated release schedules or processes following this model and it scales from a team of 1 to a team of 1000, I've seen it done.
Gitflow doesn't work in a CI environment on a modern software application that has good testing culture and systems that are resilient to failure.
Tools and processes work a lot better when they work for you, not the other way around. KISS.
> There's no need for tags, complicated release schedules or processes following this model and it scales from a team of 1 to a team of 1000, I've seen it done.
How do you roll back in a process like this? I was imagining that a release would consist of tagging master, so a rollback would be going back to the previous tag. Or perhaps you just keep track of the previously deployed commit hash and roll back to that?
I have used gitflow successfully for some time (starting when it was first announced and there wasn't anyone complaining about it). I've always done "develop is always deployable to production" and the only thing we used master for was rolling back (extremely rare), and the only thing we used release branches for was demos or documentation before a release went out. We had CI built against develop but also every feature branch and every PR. We also leveraged static analysis the same way, and at one company even ran automated pen tests on develop and PRs.
I don't know if I fundamentally misunderstood gitflow but this was my take on it from the beginning and I've never had issues with it that made me want to jump ship.
We didn't use hotfix or support branches, and we never really used tags for anything either. Not using them didn't cause any noticeable overhead.
The nice thing about git-flow in my opinion is that you can implement it without all of the CI stuff, then add that later over time. This is a godsend when you take over a legacy product with little to no test coverage and no CI pipelines.
I've also never run into a ton of merge conflicts, but the largest team I've had is 70 people so maybe it breaks down at some point that I haven't experienced yet.
> Gitflow doesn't work in a CI environment on a modern software application that has good testing culture and systems that are resilient to failure.
Sure it does.
It isn't necessary in such a culture if there aren't bureaucratic barriers to continuous deployment which limits you to continuous delivery.
If you have such barriers, you very quickly need Gitflow’s split between permanent “develop” and “master” branches as well as temporary “release” branches.
Source repositories are all about managing complexity. The more unmerged code you have from your releasable branch... the more complexity you have being held in the source repository.
In the field I've seen git-flow lend itself to having trouble handling releasing some features and not others that have already been merged into a release or environment branch. This leads to cherry picking or more complex merging trees. With trunk based development, once a thing is merged to master it is shipped.. so it keeps the complexity being held in unmmerged branches to a minimum.
Are people really calling this specific model of git branching THE Gitflow model ? For me this was a gitflow amongst others, a gitflow being a git workflow.
In the original article "A successful Git branching model" I don't see a single mention telling people they should call this specific model Gitflow.
For me the word gitflow has the useful meaning of a git branching model, am I in the minority ? Using it as a noun for a specific model seems like a waste of the word.
In regards to the article, sure this gitflow is one of the most shared images on the subject. However I recommend that every team use whatever gitflow makes the most sense for them and their project. I was not aware that our industry had a problem with teams cargo culting that specific git workflow.
+1. We use as many branches as it makes sense on a particular project. Simple ones might have just master (and temporary feature/bugfix branches). Only when we need to have a LTS version do we introduce another branch for it.
I always thought this is also Gitflow, but reading this article, I'm not so sure anymore.
We don't use any branching. Git is complicated enough to explain to non-software engineers without branching. We treat all commit versions equally for CI/CD. As most people are not software engineers, this seems a reasonable course of action if a project encompasses non software elements. We have non CI/CD testing anyway (nontrivial hardware projects require much more external process).
For releases we assign versions without tags, instead using replication of a subdirectory tree under a version number. This ensures all versions are available locally to all users without adding any access complexity.
This is basically optimizing for simplicity for the users.
100% agreed. The workflow suggested in the viral blog post is far too complicated, even for experienced teams. But in practice what happens is that the teams who are most likely to base their git practices off some random blog post instead of off their own experience are the least experienced teams.
I will admit I would not know the difference between gitflow and a hole in the ground. But that diagram looks an awful lot like the workflow you tend to pick up when using fossil.
* The primary dev branch
* branch and merge for feature development
* long term branch for each release.
The authors only real concern appeared to be no rebase, and rebase is already a big no-no in any sort of distributed development, just adopt that attitude for your personal development.
> The authors only real concern appeared to be no rebase
This is my take as well. That blog post has not much to say about anything, mostly weak points stemming from personal distaste of some things, but it boils down to 'i like rebase more'.
> rebase is already a big no-no in any sort of distributed development
You are ill-informed on this subject, and I have a proof-by-existence.
Sun Microsystems, Inc., used a rebase workflow from the mid-90s all the way until the end, at least for the codebases that made up Solaris (OS/Net and other consolidations), and it did so while using a VCS that did not support rebase out of the box (Teamware, over NFS). It was essentially a git rebase workflow years before Larry McVoy created BitKeeper, and even more years before Git was created, and even more years before the rebase vs. merge workflow controversies.
When I was at Sun we had ~2,000 developers on mainline Solaris. The rebase workflow worked fantastically well.
Large projects had their own repositories that were rebased periodically, and team members would base their clones on the project's clone (known as a "gate").
Large projects' gates would get archived for archeological interest.
All history upstream was linear. No. Merge. Commits. (We called them "merge turds", and they were a big no-no.)
Solaris development was undeniably distributed development.
Rebase workflows are the best. We used them at Sun long before anyone called it rebasing, long before even any VCSes had the feature in any way. It's the only workflow that works in large codebases (monorepos, repo forests) with thousands of developers. Merges stop being interesting very quickly once you've got a) a large number of developers, and b) a high rate of commits on the same codebase -- it's just too much metadata.
Linear history works like a charm and is super easy to understand (because it's linear).
Nobody cares about the internal history of a feature branch that has delivered. One should only care about what mainline bugs were fixed and what features were added -- bugs that never made it to the mainline are simply not interesting at all to developers on the mainline (though admittedly they might be to someone studying developer performance, but then, feature branch history can be kept and archived, just not on the mainline).
My only beef with rebasing is that it seems to fail much more often, whereas merges will usually do the right thing. I realize this is git-specific, but rebases have still given me much more trouble than merges.
I've yet ever to see a rebase workflow fail, and I've been using a rebase workflow since at least 2002.
I do sometimes have to rebase across thousands of commits because I let a branch rot, and that can be hard to rebase, but it can be equally difficult to merge. Instead I use a bisecting rebase approach where I try to rebase straight to the new upstream, and if there's conflicts, abort the rebase and try rebasing to halfway to the new upstream, continuing the process until the rebase was across just one commit, thus I can resolve conflicts directly with the upstream commit that caused them, then restart the process until done.
Hmm, that doesn't match my experience. If I remember correctly, I've mostly seen long-running branches where the conflicting code was moved/taken care of still having rebase conflicts because git is running the commits one by one, and is conflicting with the old commits (before they were fixed), requiring me to fix them yet again.
Merging doesn't have that problem, it usually just merges fine unless there are conficts in the latest commit (not all previous ones).
> I've mostly seen long-running branches where the conflicting code was moved/taken care of still having rebase conflicts because git is running the commits one by one, and is conflicting with the old commits (before they were fixed), requiring me to fix them yet again.
No :/ I had it enabled, which is why I'm surprised it happened. Unfortunately it was long ago that I don't remember details, but I've had my "merges are much easier" opinion reinforced by git multiple times.
I was on a team that “merged forward” from base branches in subversion back then. What I learned later was that was one of the few teams that was a actually doing that in svn.
Yes. Teamware with Casper Dik's "turbo" extensions. We used that at Sun, with a rebase workflow going back much earlier than 2002, but 2002 is when I joined Sun.
Recall that "rebase" == identify the end of the linear history in common between this branch and the upstream, call that the merge base, identify local commits between that merge base and the head of this branch, checkout the upstream head, and cherry-pick (sequentially apply) those commits as if de novo (possibly recording this action in new metadata).
One can implement that even with Fossil or any other VCS that pretends it does not implement rebase and pretends it never will.
Do you have a tool to assist with such rebase? Or something to read? I also prefer linear history without so much superfluous merge metadata, so I'd like to learn more on this.
It's amazing how I'd consider myself as having a pretty good grasp of Bash programming, certainly more than average among my colleages, and still this code got me already in the second line :-) (never used typeset before)
I find it interesting that many people don't seem to know the "git rerere" option [1], even experienced devs. With long lived feature branches that takes away 95% of the frustration people have with rebasing.
Theoretically, one could also use merges on the feature branch and rebase once at the end of development (as git will auto-remove all merge commits during rebase), but that only works well if you have just a single commit between merges on the feature branch.
Most of that blog post's workflow seems like pretty normal merge request development. Separating develop and master is where most of the complexity arises. The reported advantage is "the develop branch is cleared to receive features for the next big release". I have never ran into a problem with features needing to land in master before a release is cut, likely because I have never scheduled releases and I think most projects don't. Even if they did, the project has to be pretty massive to have a feature ready, but scheduled for a future release and also be blocking the development of another scheduled feature... If your project is that busy, it is seems like a reasonable workflow. Everyone else can probably just treat master as their develop branch and everything else in the article is pretty good advice.
The only other oddity I see is treating hot patches different than feature branches. In my experience, hot patches are no different than feature branches in projects that use master as the branch to deploy from. In projects that perform manual QA, I use a branch for each deploy environment to stagger rollouts, the final branch being for the production environment. In that case it makes sense to start a merge request on the production branch before master.
Gitflow didn't just pop into the head of Vincent Driessen. It seems he curated an opinionated selection of the options from the book Pro Git (https://git-scm.com/book/) and I wouldn't be surprised if many projects were already using something like it to various degrees.
I went for many years with only a master branch and sometimes a develop branch, because I often worked alone. It took me years to venture into branching at all. Before Git I used Subversion. I don't think we branched once. But easy branching is one of Git's distinguishing features. For me, branching was like learning a programming language. At first it's mindbending and intimidating. But with reading, practice, re-reading, and more practice, it can eventually become second nature. The crazy diagram that George Stocker holds up makes perfect sense to me now.
I was forced to adopt Gitflow when I joined a bigger team. But now that I have learned it, I kind of like to use it even when working alone. Topic branches remind me of functions, in that they are small and encapsulated. I can concentrate on a narrow range of code and feel safe. The eventual merge might have conflicts, but they are soluble. And the way that feature branches stem from develop while bug-fix branches stem from master, and how you have a release branch to freeze features without freezing work --- I don't know, it feels very safe and structured.
However, yeah, like Stocker says, it may be too much ceremony, especially if you're just starting out. I like to tell people to ease into it. Stop when it hurts.
The essence of it is establishing different roles for different branches. mainline, development, maintenance, accumulation and packaging.
With those roles in mind, when I was introduced to git flow it made sense - mainline is develop branch; development and maintenance roles are done in feature branches. Accumulation isn't one that is seen too often but should be kept in mind, and the release branch is the packaging role.
These ideas have probably been realized time and time again.
The conclusion of the paper:
> Planning and analysis are critical to the success of any SCM system. A branching strategy motivated by a risk-based analysis of the organization's development needs will provide a strong foundation. Incorporating the concepts of branch roles, codeline policy and codeline ownership will assist in performing the required analysis. Application of the principles of branchpoint, merge policy and branch life span will ensure that the parameters governing codeline policy are properly and completely addressed.
> Once the branching strategy has been formulated, the organization can implement the customizations required to make the SCM tool suit its environment. Until SCM systems have reached sufficient maturity to address the larger issues of policy, adopting the practices put forth in this and other papers will help an organization achieve success in their software development endeavors.
Yup. It's a byproduct of software not being grounded in anything compared to, say, every other engineering discipline. They all have the laws of physics. Software has...a bunch of different mantras and paradigms, and for every one out there, there's one that is its direct opposite.
Even things that have science are largely ignored - one I always shake my head at - oracles for ethereum. Proved many years ago - there can't be an oracle. Ethereum developers - we'll build oracles so the transactions are guaranteed.
No doubt there will be arguments for how oracles for ethereum are different, and so on
> It's a byproduct of software not being grounded in anything compared to, say, every other engineering discipline. They all have the laws of physics.
I think experimental evidence helps, but if you look at the physical sciences more closely, you'll find tons of similar narratives. This is a fairly universal human behavior unfortunately. Nonsense becomes "canonized" as I put it, and then continues to be repeated by people until someone finally looks into it and realizes it's nonsense and publishes an article saying so. But unfortunately that's not always the end of the nonsense. Even things which have been debunked can continue to be cited and used. One great example (not engineering but the point stands):
> In one sense we won. We got our points across. People now understand that this research is wrong. But this 2005 article by Fredrickson and Losada gets citations today at 3 times the rate of our article that demonstrated that it was just utter rubbish.
(Note that I'm using "nonsense" as an example here, but the top level comment was more general in that it mentions practices which apply in some situations erroneously being applied for all situations.)
My mind was blown when I found out that daily standups were a Kanban philosophy and not a SCRUM philosophy. Only because every SCRUM team I have been on has standups and it is essential, as long as they are less than 1 minute long.
Also not in XP. I eventually came to like standup meetings, but with one caveat: no management (including project management) is allowed to attend. Otherwise it becomes a status meeting rather than a "How can we get past our current blockers" meeting. Management glazes over all the technical talk -- the very thing that we need to speak about if we are to need a meeting at all.
I'm going to say this rather rashly (and maybe regret it sometime in the future): any "Agile" process that includes a status meeting for developers is broken. Status should be determinable from the artifacts that have been produced. If management can not see or understand the artifacts, then your process is broken. If they prefer not to look at the artifacts, then your management is broken. If they need status on something that is "taking too long" then you haven't broken up your tasks enough. If you have broken them up enough and it's still "taking too long", then there really isn't much to say other than "this blew up on us" -- which is obvious.
What a standup is good for is casually checking with your teammates that the approach you are taking is reasonable and to discuss other strategies. It's useful for asking for help, swapping pairs (or getting one in the first place). If you find yourself doing the "This is what I did yesterday. This is what I'm going to do today" dance, then you are not getting much value. It should be blindingly obvious what you did yesterday, because code was written, reviewed and hopefully merged. Possibly you may want to say, "Hey, can you review my code?" It should be blindingly obvious what you are going to do today, because you grabbed a card/task from the backlog. The only thing you need to talk about is, "I'm confused. How do I do this?" and the like.
> status should be determinable from the artefacts that have been produced.
Hell yes! Status meeting can be a band aid while you get people to properly document and communicate those though. You often don’t need the whole team for that though.
My takeaway from this is that more articles should include a 'this works in x situation, probably also works in y, but is not suitable for a, b, c' discussion. Applying the right techniques in the right places is an important part of engineering - some authors talk about it more than others and it's very useful.
I don't understand the argument here at all. Git flow seems pretty orthogonal to concept of branching lifespan. We did the "merge early, merge often" approach with SVN 15 years ago and it was fine. We do git flow now and it's fine. It meshes perfectly with agile development where you work on the smallest feature set that adds incremental value. That means your branch only ever lives long enough to do one tiny thing and it gets merged as soon as it's working and no sooner. I've been following this approach for years with dozens of teams and it's very successful. And I've never run a rebase on purpose in my entire life.
I have some long-lived branches lying around for work I only occasionally have time and energy to do. E.g., I've an "ALWAYS DEFERRED" feature patch for PostgreSQL I need to eventually finish. Every time I come back to it I've fallen thousands of commits behind, and neither a merge nor a rebase can save me, but a rebase bisection script I have does save me by identifying the one commit upstream, in order, that causes conflicts that I have to resolve manually, then resumes the rebase bisection.
Specifically, the algorithm is something like this (not tested; I've a script I should publish):
bisect_rebase() {
local ultimate_target=$1
local target=$2
shift 2
b=$(git merge-base HEAD $target)
while [[ $b != $(git rev-parse $target) ]]; do
n2u=$(git log --oneline $b..$ultimate_target | wc -l)
n=$(git log --oneline $b..$target | wc -l)
# Try rebasing directly onto the target
git rebase --onto $target $b && return 0
# If we have conflicts and rebased across just
# one commit, stop here
((n2u == 1)) && return 1
if ((n == 1)); then
echo "Fix conflicts and exit 0 to continue or 1 to stop"
if $SHELL -i; then
git rebase --continue
return 0
else
git rebase --abort
return $?
fi
fi
git rebase --abort
bisect_rebase $ultimate_target $(git log -n $((n/2)) --pretty=%h $b..$target)
done
}
The nice thing is that git is serverless, so you can clone a throwaway repo and run this sort of risky thing safely. It makes what's impossible in SVN possible, though maybe not easy.
Oh get off your high horse. Git started as a collection of small programs and shell scripts, and as time went by more of those scripts became programs.
How it came to be is basically irrelevant when determining how materially useful it is, given all the bizarre artifacts of git. Nobody really seems to really have mastered it, most people seem to grasp only a subset, and there are so many potential pitfalls. It's a very powerful, raw technology that hasn't been properly productized, or rather, 'it works how Linus wants it to for his reasons' and everyone else just gets dragged along.
I'll bet $1000 that zero of your colleagues have truly mastered git.
I've watched countless times as employee X did something wrong, the so-called 'git experts' gaggle around them and spend quite a bit of time trying to 'fix' the situation, all with varying approaches that their peer gitters barely understood. All blissfully unaware that their 'intelligence signalling' is woefully misplaced as such situations should not arrive in the first place, and if they did, they should be easily remedied.
Moreover, it doesn't matter that 'a few people' have very strong Git skills, the point is - the vast majority don't and there should absolutely be no need for them to - the problems most developers face re: code management are simply not complex enough to warrant the power of the tool. The failure to understand this among so many glib gitters is basically existentially problematic. The inability to grasp the difference between 'raw power' and usability, complexity and the resulting costs ... is the real problem.
"Whatever you call your branching methodology, if they last too long that's when the fun stops."
Doesn't git-flow explicitly keep a long lived branch around by design? The whole concept of having "develop" run in parallel to master is introducing a long lived branch. That's typically the branch that I'd always have the most trouble with.
That's assuming that there is anything going on on master at all. A gitflow master doesn't really count as a branch of it's just a permanent alias for the latest mainline release tag.
Often when I encounter (startup) teams using this git-flow inspired strategy there definitely are things going on with master that shouldn't be. For example:
Feature A is in staging ('develop'), but can't get into prod ('master') yet. However, the opposite is true of Feature B -- a customer needs it now and timelines get changed by sales or management (your largest customer needs it now). It conflicts with something in A and can't go into staging just yet (another team needs it). So that feature branch needs to go straight into master without hitting develop. The whole deployment infrastructure was designed on the (false) assumption that develop is always deployable to staging, and master to prod, rather than being able to quickly deploy and test feature branches at whim. So now we've diverged between master and develop a bit, and while we could still get our way back to a "clean" git-flow at this point pretty easily, if you're not careful this can keep compounding. I've seen it compound for months, and personally have wasted days trying to clean up conflicts that set in because teams I'm consulting for weren't careful.
It's easy to have an inexperienced startup team make these git-flow based decisions early on, get stuck with them for some time, hit rapid growth, and then get themselves into a messy place.
My point is sure, use it if you have pretty steady release and deploy schedules. But if you're deploying dozens of times per day you need to design your infra and CD strategy to handle it. Typically I've seen teams with fragile deploy strategies they've adopted due to assumptions they made from starting with git-flow.
So why even do it? There are simpler strategies like GitHub Flow that force a team to design a deployment strategy that accepts that feature branches can be tested in a real environment, and master can always be delivered (or rolled back).
What sort of repository and deployment structure are you using right now in which it works fine? I think that will influence the outcome a lot.
I just was working with a client that used something like git-flow, where develop was deployed to staging in order to test, master was always production, and the codebase is largely a monorepo. Then there were a couple other legacy repos, which also are using git-flow. It... "works", but it also is a needless source of pain. You need to PR to develop, then PR develop into master, and I'd inevitably get bitten with merge conflicts in the process. All that for what gain? I saw no upside to it. Maybe if you have steady release cycles, but git-flow never seemed to fit the whole disposable branches, master is good to deploy dozens of times per day sort of workflow I've gotten used to.
Just pull develop into your feature branch daily. Merging develop to master is a one-lane highway so merges are only required if you did a production patch.
Continuous deployment triggered by a merge into develop is basically a degenerate case of gitflow where there is an automated release associated with every merge into develop.
So if you are doing full gitflow or if you are doing this degenerate case of gitflow you still shouldn't be getting merge conflicts when releasing develop (merging develop into master). This should basically be a fast-forward with perhaps a merge commit for record keeping. The only way to get conflicts in this case is if there is some other process that is changing master independent of the "releases" from develop.
In gitflow those other changes are managed through the hotfix branching rules, which ensures that you resolve the conflict when you close the hotfix and back merge it into develop.
> I've never run a rebase on purpose in my entire life
While it's great that you've found a branch strategy that works for you, I would hesitate to take recommendations from anyone who doesn't rebase their patches. Then it's just an elaborate way of doing cvs style development.
Which there is nothing wrong with of course. That works great for many people. It's just not what git does best.
Git was built for giant open source projects where you have dozens of contributors making unplanned code changes to an organically growing code base. That's not a use case for any well-managed enterprise. Pull requests come a few at a time and representing a few days work and are rarely stepping on each other. Every conflict can be worked out face to face very quickly. If I have to manage a large group of devs, I break them up by vertical so they're not on top of each other.
This is the thing I've never really understood about the common objections to merging and resolving conflicts in larger projects. Sometimes people talk as if that happens all the time and it's not scalable if you have hundreds or thousands of developers all working on some huge code base. But how do you even get hundreds or thousands of developers working on the same huge code base so they keep getting in each other's way? Where is the modularity and coordination?
It always sounds like this happens at a hellish organisation where some Agile consultant once came in and said not to bother with boring stuff like management or software architecture. These must be strange places to work, because reportedly they also need to be prepared for requirements to change significantly every 27 seconds, and not being able to deploy changes in minutes is an existential threat even though the new feature has barely finished running the automated test suite and doesn't yet have any kind of user documentation, knowledge among the sales and support teams, etc.
Personally I do find rebasing and squashing to be very useful in workflows that involve Git, but there are plenty of effective ways to run a project and use a source control tool that don't rely on a 100% linear history with GitHub-style pull requests for change management.
Some people talk about merge conflicts as something inherently bad, but that's a flawed perspective. Merge conflicts are a great feature of a version control system. Given that multiple persons changed the same line, conflicts are the easy way out.
Conflicts have only given me a hard time when someone did something out of the ordinary. Even very large and unstructured open source projects such as the Linux kernel will see people naturally gravitate to different parts of the code. It's not often a filesystem developer suddently change the networking stack, for example.
401 comments
[ 3.3 ms ] story [ 297 ms ] threadhttps://trunkbaseddevelopment.com
"A source-control branching model, where developers collaborate on code in a single branch called ‘trunk’, resist any pressure to create other long-lived development branches by employing documented techniques. They therefore avoid merge hell, do not break the build, and live happily ever after."
In my experience, new/small teams do well if they stick the "Scaled Trunk-Based Development" model until a legitimate reason to deviate is discovered (e.g. needing to back-port changes to an older release may imply making commits to non-trunk/master branches...).
Thinking about the purpose of branches, thinking about whether everybody is on the same page and what mistakes are possible, thinking about useful rules about changes and merging (possibly on a branch by branch basis), thinking about when to break and how to adapt the rules, and above all thinking about the objective of making correct and low-effort merges.
Adopting practices because a blog post says so is the opposite of maturity. As Gitflow is presumably a good fit for the project it originated in, any "alternative styles" are suitable for someone else's particular needs and should be treated as examples and anecdotes illustrating general principles.
Both of these models simplify Gitflow by dispensing with the long-lived development branch and therefore the complication of needing separate hotfix vs release workflows.
The difference between these models is that Github Flow expects you to deploy to environments within a pull request before merging to master, whilst Gitlab Flow expects you to merge to long-lived environment branches for deployment (presumably using Gitlab's CI features).
[0] https://guides.github.com/introduction/flow/
[1] https://docs.gitlab.com/ee/topics/gitlab_flow.html
There are things in this article I agree with, and things that I don't, but the quoted point is something that I wish could be universally understood. Some developers commit to the dogma of one blog post or another and forget about the fact that the whole thing is for the _people_ who are writing the code. Branching strategy should help to optimize workflows and minimize friction, regardless of how badly bastardized your approach is vs. its source material.
Nowhere is this more apparent than when we argue about test coverage %'s. There's a whole bimodal distribution of people very wrong for very different reasons.
(Personally I think tests keep me from breaking my and others' code, but I don't tell them that)
For me, it’s frustrating to see people make in-depth, well-considered points about why something is problematic, and have that be met with “well you just need to pick the right tool for the job guys!” It’s such an anodyne and vacuous point to make, precisely because the whole dialog is around whether and when a tool is the right one.
Given a job, people will disagree about what the correct tool is. Given a tool people will disagree about what jobs it’s good for. There is no way around this, and there are times when a decision must be made.
Instead of doing the whole thing, we had feature branches (which I still hate), master, and one more branch for the stuff we were showing to the customer. Who sometimes would decide they didn't like what they asked for and please don't push this to production.
With the exception of hotfixes, master was always just a certain number of commits behind the working branch.
Very aggressive use of dark launching of features could also solve this problem, but we've had our share of problems with that strategy too (Sprint-obsessed thinking makes it difficult to go back and clear out old conditionals once they've settled)
Most obviously, the boundaries of source code repositories should be aligned with released modules: if "the system becomes a manifest of the different revisions of the different repositories" the repositories are too fragmented (or the releases too monolithic), if "teams are independent and microservices should be independently deployable" disparate components should not share a monorepo, and in both cases the difficulties are consequences of bad architectural choices, not of branching models.
Switched at some point to GitHub flow and never looked back.
It’s a mediocre branching model incapable of handling a modern workflow, like continuous delivery and so on
We gotta tendency to excuse bad software as long as it’s old, especially on HN
And the beauty is, if a team wants to be more "agile"/more continuous, all we have to do is kill a few branches, and start building/releasing directly from master.
Why do you use agile in quotation marks? Is there something wrong with your keyboard? What’s the deal?
--- doesn't sound like Gitflow. In Gitflow, the topic branches have been merged into the develop branch first, as they were finished. In contrast, merging into master is a merge from a single branch. You branch from develop into a release branch. Then you merge the release branch into master.
Release branches should be created shortly before release, and shouldn't deviate too much from develop. Feature branches also shouldn't last very long.
If a feature is going to be under very heavy development before shipping, a better strategy is to #ifdef the feature. This helps avoid accumulating merge conflicts that happen when there are long lived branches.
These are cases necessitating a manual testing step before releasing to prod, and manual testing will often uncover bugs that need fixed. Thus, you need to be able to fix these and continue testing, all the while having as little impact as possible on other Devs working on things unrelated to this release.
Having either a single long-lived release/QA branch or shorter-lived release-specific branches accomplishes this in a reasonably simple way.
That's what I meant by real-world software development. If you work at a shop with an amazing test suite and don't need these steps, good for you. But, in my 15 years of development, I've never seen a shop like that.
Their criticism about "tripling the number of merge conflicts" because of the number of branches doesn't make any sense. As long as developers are doing development work and committing, regardless of what branch they're committing to, there is potential for conflict. It might not be a "merge" conflict in the sense of two separate branches, but it will manifest as a merge conflict in pushing the local to the remote. The potential for conflicts stay the same. What git flow gets right here is it isolates logical workflows from each other, so people working can work for as long as necessary without conflict.
>Gitflow abandons rebasing
Rebasing is a nightmare for distributed work, and in my opinion, only makes sense in limited circumstances where your code is not already pushed and pulled in multiple locations.
>Continuous delivery is a practice where the team release directly into production with each “check-in” (in reality, a merge to master), in an automated fashion. Look at the mess that is gitflow and explain to me how you’re going to be able to continuously deliver that?
Every modern CI/CD framework can run automated jobs after a merge into master, so I'm not sure what the criticism here is?
>Have you ever tried a complex branching model like gitflow with multiple teams, and hoped for everyone to be on the same page? Can’t happen.
That is less a criticism of git flow and more a criticism of any software organization that tries to have repeatable deployments with many services. It's a difficult problem in general, and not one that git flow is attempting to solve in the first place. You will have that problem regardless of if you use git flow or not.
I could go on but there's a lot here. It sounds like the author is very frustrated and annoyed with git flow, and perhaps is used to cowboying code (the desire for frequent rebasing give me a hint to this) without regard for the impact on other developers. I've worked with people like this, and they often provide no alternative solutions, just frustration and resistance to following an imperfect process. It's a rant without much substance.
The criticism (and the one thing I can sort of agree on) is that with git flow you are not merging to "master" on a continuous basis. Select quotes from the nvie post describing gitflow:
> When the source code in the develop branch reaches a stable point and is ready to be released, all of the changes should be merged back into master somehow and then tagged with a release number
> The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release)
> By doing all of this work [release prep] on a release branch, the develop branch is cleared to receive features for the next big release.
My company does exactly this and I am happy to report there have been no issues. I think the key reason we don't have issues is we are strict about maintaining backwards compatibility between services and also try to maintain forwards compatibility where possible.
> “What’s in production” becomes an existential question, if you’re not careful.
We solved this by embedding the SHA's of a build's constituent repos in the build artifact.
* major features are done in feature branches, w/rebasing prior to merge
* minor stuff directly in develop
* master is auto deployed following successful CI, whenever we merge develop in to it
* we merge frequently, but not automatically
* we tag releases manually when we do merge
It's a more minimal version of git flow. Small teams so not much problem.
We could probably just drop the develop / master split and still be fine, but would force all changes to be in feature branches instead.
Also for DevOps you sometimes need to be able to branch off Master to apply a critical patch which then gets merged back into Dev later. You don't want to ever need to do that, but if subverting the normal process makes sense because you have all signoff parties gathered at the table - you do what needs to be done.
There was also some wishful thinking about doing more qa testing than anyone actually did. The develop branch would immediately deploy to the staging environment, so someone might have tested new features there before they ship to production. But if there’s no rigorous process around exactly what needs to be QA’d and whose responsibility it is, then let’s be realistic, it’s not gonna happen.
The downsides are that release times were less predictable, deploys were bigger which means potentially more difficult to trace down bugs that do show up and roll back when needed, and things would get delayed for no reason. Oops, I thought I shipped that thing for marketing a few days ago but nobody deployed the develop branch since then.
Developing small features right into develop sounds like a bit of an issue on its own too. Seems like you’re not quite confident enough to deploy it right away, but it’s also presumably circumventing the regular code review process so it’s not going to get reviewed.
The only reason I can see for why these downsides would be worth it, is if you have some hard constraint that you can’t deploy very frequently (for instance releasing a downloadable desktop app or mobile app), and/or you have a formal, rigorous manual QA process when merging from develop to master.
One exception might be the occasional group of optimists trying their hand at micro repos. These are just bound to blow up :-D unnecessary conplexity and all...
Relatedly is "release branches". An alternative is to simply tag the release that went out, which is the same thing. If it needs a hotfix, you branch off the tag, fix it there, then apply that fix (cherry-pick or redo) back to master.
Overall, IME the biggest benefit is the cultural changes it instills in the team: Everything must be good enough to release, and everything goes to the same place. For projects that can afford it (again, most can I bet) its a huge drop in mental effort to understand the state of the world at any given time.
So what? Those branches live for exactly as long as the minor stuff takes to develop and review.
Rebase in a feature branch, that can be long-lived and have many commits, seems like a painful experience to me.
You can end up solving the same conflict more than once, or even solving conflicts that don't exist in the final result. no-ff merge commits are usually easier to solve.
Am I missing something? Is there an easier rebase strategy?
We actually merge the master into our long lived feature branches first. Then run all the tests on that branch, if it's good it can be directly merged into master (master is locked, and you need permission to commit anything to it).
no-ff merges are easier, but leave a messier non-sequential history of when things actually go out which is sometimes confusing when understanding why things are the way they are; I generally, but not always, judge it to be worth the pain!
It keeps coming up in my consultancy work, usually on short term projects that either die or generally just get left to tick over where it's wildly unsuitable. Mostly because of the way it violates that principle of short lived branches.
I loved the concept of git flow when I first read that legendary blog post. I learned a lot and adapted it into my own development workflow. I've bounced back and forth over the years in how strictly I adhered to the One True Way (tm) based on how well it worked for me in actual projects.
IME I think the best approach to git flow is to learn and understand it and then adapt it to your project's workflow, as opposed to strictly adhering to every tenet of git flow. I have multiple projects using different "amounts" of git flow - e.g. a large project with dev, qa, hotfix and release branches vs a small personal project with only master and dev.
I agree, as with most things, there certainly is room for flexibility here.
One problem I've seen repeatedly occur when migrating to git flow is a misconceptions about 'bugfix/' branches, which are intended to be used when stabilizing a 'release/' branch. However devs use that prefix for every bug they find which is not related to a story/feature. And to be honest, they are right to do so. The naming is just bad here, since the term 'bugfix' is so generically used, it's not very intuitive to use it only for release branches. So I've come to the point where I would agree to use 'bugfix/' for regular bugfixing if the team/company is comfortable with it, even though it is opposed to original gitflow.
Gitflow doesn't work in a CI environment on a modern software application that has good testing culture and systems that are resilient to failure.
Tools and processes work a lot better when they work for you, not the other way around. KISS.
Use something by applying it with common sense, in the right amount and customization and it will have a chance to work.
Use something as if it is a religion and it will introduce weird side effects.
How do you roll back in a process like this? I was imagining that a release would consist of tagging master, so a rollback would be going back to the previous tag. Or perhaps you just keep track of the previously deployed commit hash and roll back to that?
I don't know if I fundamentally misunderstood gitflow but this was my take on it from the beginning and I've never had issues with it that made me want to jump ship.
We didn't use hotfix or support branches, and we never really used tags for anything either. Not using them didn't cause any noticeable overhead.
The nice thing about git-flow in my opinion is that you can implement it without all of the CI stuff, then add that later over time. This is a godsend when you take over a legacy product with little to no test coverage and no CI pipelines.
I've also never run into a ton of merge conflicts, but the largest team I've had is 70 people so maybe it breaks down at some point that I haven't experienced yet.
In my setup I have a develop branch and the idea is that anything in it can be deployed to prod. Of course, that is if nothing fails.
If nothing fails, it merges with master (what’s actually on prod).
Sure it does.
It isn't necessary in such a culture if there aren't bureaucratic barriers to continuous deployment which limits you to continuous delivery.
If you have such barriers, you very quickly need Gitflow’s split between permanent “develop” and “master” branches as well as temporary “release” branches.
In the field I've seen git-flow lend itself to having trouble handling releasing some features and not others that have already been merged into a release or environment branch. This leads to cherry picking or more complex merging trees. With trunk based development, once a thing is merged to master it is shipped.. so it keeps the complexity being held in unmmerged branches to a minimum.
In the original article "A successful Git branching model" I don't see a single mention telling people they should call this specific model Gitflow.
For me the word gitflow has the useful meaning of a git branching model, am I in the minority ? Using it as a noun for a specific model seems like a waste of the word.
In regards to the article, sure this gitflow is one of the most shared images on the subject. However I recommend that every team use whatever gitflow makes the most sense for them and their project. I was not aware that our industry had a problem with teams cargo culting that specific git workflow.
I always thought this is also Gitflow, but reading this article, I'm not so sure anymore.
I have heard the terms "git branching model" or "git workflow" used for the concept that you call "gitflow".
Plus nvie.com updated its 10-year old post with a notice yesterday and also uses the name git-flow there.
I guess I'd better use the term git workflow in the future.
For releases we assign versions without tags, instead using replication of a subdirectory tree under a version number. This ensures all versions are available locally to all users without adding any access complexity.
This is basically optimizing for simplicity for the users.
This is my take as well. That blog post has not much to say about anything, mostly weak points stemming from personal distaste of some things, but it boils down to 'i like rebase more'.
You are ill-informed on this subject, and I have a proof-by-existence.
Sun Microsystems, Inc., used a rebase workflow from the mid-90s all the way until the end, at least for the codebases that made up Solaris (OS/Net and other consolidations), and it did so while using a VCS that did not support rebase out of the box (Teamware, over NFS). It was essentially a git rebase workflow years before Larry McVoy created BitKeeper, and even more years before Git was created, and even more years before the rebase vs. merge workflow controversies.
When I was at Sun we had ~2,000 developers on mainline Solaris. The rebase workflow worked fantastically well.
Large projects had their own repositories that were rebased periodically, and team members would base their clones on the project's clone (known as a "gate").
Large projects' gates would get archived for archeological interest.
All history upstream was linear. No. Merge. Commits. (We called them "merge turds", and they were a big no-no.)
Solaris development was undeniably distributed development.
Rebase workflows are the best. We used them at Sun long before anyone called it rebasing, long before even any VCSes had the feature in any way. It's the only workflow that works in large codebases (monorepos, repo forests) with thousands of developers. Merges stop being interesting very quickly once you've got a) a large number of developers, and b) a high rate of commits on the same codebase -- it's just too much metadata.
Linear history works like a charm and is super easy to understand (because it's linear).
Nobody cares about the internal history of a feature branch that has delivered. One should only care about what mainline bugs were fixed and what features were added -- bugs that never made it to the mainline are simply not interesting at all to developers on the mainline (though admittedly they might be to someone studying developer performance, but then, feature branch history can be kept and archived, just not on the mainline).
I do sometimes have to rebase across thousands of commits because I let a branch rot, and that can be hard to rebase, but it can be equally difficult to merge. Instead I use a bisecting rebase approach where I try to rebase straight to the new upstream, and if there's conflicts, abort the rebase and try rebasing to halfway to the new upstream, continuing the process until the rebase was across just one commit, thus I can resolve conflicts directly with the upstream commit that caused them, then restart the process until done.
Merging doesn't have that problem, it usually just merges fine unless there are conficts in the latest commit (not all previous ones).
is this solved by enabling git-rerere ?
https://medium.com/@porteneuve/fix-conflicts-only-once-with-...
Also, with this script you get to see which of your commits is conflicting with which upstream commits. That's really important information to me.
I'd really like git to have this feature built-in to it...
One can implement that even with Fossil or any other VCS that pretends it does not implement rebase and pretends it never will.
(Viktor here is https://github.com/vdukhovni/, and I did heavily alter that code.)
Thanks for the gist
Theoretically, one could also use merges on the feature branch and rebase once at the end of development (as git will auto-remove all merge commits during rebase), but that only works well if you have just a single commit between merges on the feature branch.
[1] https://git-scm.com/book/en/v2/Git-Tools-Rerere
[0] https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee650...
The only other oddity I see is treating hot patches different than feature branches. In my experience, hot patches are no different than feature branches in projects that use master as the branch to deploy from. In projects that perform manual QA, I use a branch for each deploy environment to stagger rollouts, the final branch being for the production environment. In that case it makes sense to start a merge request on the production branch before master.
I went for many years with only a master branch and sometimes a develop branch, because I often worked alone. It took me years to venture into branching at all. Before Git I used Subversion. I don't think we branched once. But easy branching is one of Git's distinguishing features. For me, branching was like learning a programming language. At first it's mindbending and intimidating. But with reading, practice, re-reading, and more practice, it can eventually become second nature. The crazy diagram that George Stocker holds up makes perfect sense to me now.
I was forced to adopt Gitflow when I joined a bigger team. But now that I have learned it, I kind of like to use it even when working alone. Topic branches remind me of functions, in that they are small and encapsulated. I can concentrate on a narrow range of code and feel safe. The eventual merge might have conflicts, but they are soluble. And the way that feature branches stem from develop while bug-fix branches stem from master, and how you have a release branch to freeze features without freezing work --- I don't know, it feels very safe and structured.
However, yeah, like Stocker says, it may be too much ceremony, especially if you're just starting out. I like to tell people to ease into it. Stop when it hurts.
The essence of it is establishing different roles for different branches. mainline, development, maintenance, accumulation and packaging.
With those roles in mind, when I was introduced to git flow it made sense - mainline is develop branch; development and maintenance roles are done in feature branches. Accumulation isn't one that is seen too often but should be kept in mind, and the release branch is the packaging role.
These ideas have probably been realized time and time again.
The conclusion of the paper:
> Planning and analysis are critical to the success of any SCM system. A branching strategy motivated by a risk-based analysis of the organization's development needs will provide a strong foundation. Incorporating the concepts of branch roles, codeline policy and codeline ownership will assist in performing the required analysis. Application of the principles of branchpoint, merge policy and branch life span will ensure that the parameters governing codeline policy are properly and completely addressed.
> Once the branching strategy has been formulated, the organization can implement the customizations required to make the SCM tool suit its environment. Until SCM systems have reached sufficient maturity to address the larger issues of policy, adopting the practices put forth in this and other papers will help an organization achieve success in their software development endeavors.
* Early adopter independently comes up with an idea that works well for his/her team.
* Writes an innocent well-written article or book.
* Idea somehow becomes dogmatic. Even for situations that don't make sense.
* After some time, people rebel against dogma because they realize it doesn't make sense for every situation.
* Original idea now considered anti-pattern even though it may still make sense for some people or situations.
No doubt there will be arguments for how oracles for ethereum are different, and so on
I think experimental evidence helps, but if you look at the physical sciences more closely, you'll find tons of similar narratives. This is a fairly universal human behavior unfortunately. Nonsense becomes "canonized" as I put it, and then continues to be repeated by people until someone finally looks into it and realizes it's nonsense and publishes an article saying so. But unfortunately that's not always the end of the nonsense. Even things which have been debunked can continue to be cited and used. One great example (not engineering but the point stands):
https://www.youtube.com/watch?v=WRoe3xXFtmM
> In one sense we won. We got our points across. People now understand that this research is wrong. But this 2005 article by Fredrickson and Losada gets citations today at 3 times the rate of our article that demonstrated that it was just utter rubbish.
(Note that I'm using "nonsense" as an example here, but the top level comment was more general in that it mentions practices which apply in some situations erroneously being applied for all situations.)
I'm going to say this rather rashly (and maybe regret it sometime in the future): any "Agile" process that includes a status meeting for developers is broken. Status should be determinable from the artifacts that have been produced. If management can not see or understand the artifacts, then your process is broken. If they prefer not to look at the artifacts, then your management is broken. If they need status on something that is "taking too long" then you haven't broken up your tasks enough. If you have broken them up enough and it's still "taking too long", then there really isn't much to say other than "this blew up on us" -- which is obvious.
What a standup is good for is casually checking with your teammates that the approach you are taking is reasonable and to discuss other strategies. It's useful for asking for help, swapping pairs (or getting one in the first place). If you find yourself doing the "This is what I did yesterday. This is what I'm going to do today" dance, then you are not getting much value. It should be blindingly obvious what you did yesterday, because code was written, reviewed and hopefully merged. Possibly you may want to say, "Hey, can you review my code?" It should be blindingly obvious what you are going to do today, because you grabbed a card/task from the backlog. The only thing you need to talk about is, "I'm confused. How do I do this?" and the like.
/end rant ;-)
Hell yes! Status meeting can be a band aid while you get people to properly document and communicate those though. You often don’t need the whole team for that though.
It's a bit of a joke.
This article is full of bluster about how bad gitflow is, but very little actual reasoning why.
I don't like the ceremony all that much, but its working really well at my current large corporate gig across thousands of repos and engineers.
Specifically, the algorithm is something like this (not tested; I've a script I should publish):
It makes me believe there is a real existential problem with git as a product.
... unless changes were not already pushed and therefore 'saved'.
Git is inherently dangerous and overly complex - such a script shouldn't ever have to exist for so many reasons.
You can speak for yourself. Don't speak for me or my colleagues.
I've watched countless times as employee X did something wrong, the so-called 'git experts' gaggle around them and spend quite a bit of time trying to 'fix' the situation, all with varying approaches that their peer gitters barely understood. All blissfully unaware that their 'intelligence signalling' is woefully misplaced as such situations should not arrive in the first place, and if they did, they should be easily remedied.
Moreover, it doesn't matter that 'a few people' have very strong Git skills, the point is - the vast majority don't and there should absolutely be no need for them to - the problems most developers face re: code management are simply not complex enough to warrant the power of the tool. The failure to understand this among so many glib gitters is basically existentially problematic. The inability to grasp the difference between 'raw power' and usability, complexity and the resulting costs ... is the real problem.
Doesn't git-flow explicitly keep a long lived branch around by design? The whole concept of having "develop" run in parallel to master is introducing a long lived branch. That's typically the branch that I'd always have the most trouble with.
Feature A is in staging ('develop'), but can't get into prod ('master') yet. However, the opposite is true of Feature B -- a customer needs it now and timelines get changed by sales or management (your largest customer needs it now). It conflicts with something in A and can't go into staging just yet (another team needs it). So that feature branch needs to go straight into master without hitting develop. The whole deployment infrastructure was designed on the (false) assumption that develop is always deployable to staging, and master to prod, rather than being able to quickly deploy and test feature branches at whim. So now we've diverged between master and develop a bit, and while we could still get our way back to a "clean" git-flow at this point pretty easily, if you're not careful this can keep compounding. I've seen it compound for months, and personally have wasted days trying to clean up conflicts that set in because teams I'm consulting for weren't careful.
It's easy to have an inexperienced startup team make these git-flow based decisions early on, get stuck with them for some time, hit rapid growth, and then get themselves into a messy place.
My point is sure, use it if you have pretty steady release and deploy schedules. But if you're deploying dozens of times per day you need to design your infra and CD strategy to handle it. Typically I've seen teams with fragile deploy strategies they've adopted due to assumptions they made from starting with git-flow.
So why even do it? There are simpler strategies like GitHub Flow that force a team to design a deployment strategy that accepts that feature branches can be tested in a real environment, and master can always be delivered (or rolled back).
I just was working with a client that used something like git-flow, where develop was deployed to staging in order to test, master was always production, and the codebase is largely a monorepo. Then there were a couple other legacy repos, which also are using git-flow. It... "works", but it also is a needless source of pain. You need to PR to develop, then PR develop into master, and I'd inevitably get bitten with merge conflicts in the process. All that for what gain? I saw no upside to it. Maybe if you have steady release cycles, but git-flow never seemed to fit the whole disposable branches, master is good to deploy dozens of times per day sort of workflow I've gotten used to.
So if you are doing full gitflow or if you are doing this degenerate case of gitflow you still shouldn't be getting merge conflicts when releasing develop (merging develop into master). This should basically be a fast-forward with perhaps a merge commit for record keeping. The only way to get conflicts in this case is if there is some other process that is changing master independent of the "releases" from develop.
In gitflow those other changes are managed through the hotfix branching rules, which ensures that you resolve the conflict when you close the hotfix and back merge it into develop.
While it's great that you've found a branch strategy that works for you, I would hesitate to take recommendations from anyone who doesn't rebase their patches. Then it's just an elaborate way of doing cvs style development.
Which there is nothing wrong with of course. That works great for many people. It's just not what git does best.
It always sounds like this happens at a hellish organisation where some Agile consultant once came in and said not to bother with boring stuff like management or software architecture. These must be strange places to work, because reportedly they also need to be prepared for requirements to change significantly every 27 seconds, and not being able to deploy changes in minutes is an existential threat even though the new feature has barely finished running the automated test suite and doesn't yet have any kind of user documentation, knowledge among the sales and support teams, etc.
Personally I do find rebasing and squashing to be very useful in workflows that involve Git, but there are plenty of effective ways to run a project and use a source control tool that don't rely on a 100% linear history with GitHub-style pull requests for change management.
Conflicts have only given me a hard time when someone did something out of the ordinary. Even very large and unstructured open source projects such as the Linux kernel will see people naturally gravitate to different parts of the code. It's not often a filesystem developer suddently change the networking stack, for example.