1. 79

  2. 18

    My biggest problem with git-flow is that it has enough popularity to be rubberstamped on projects (“We do git-flow here?” “yes”) and weakly defined enough to evolve into something I call “X as practiced”. Most projects I was in that did git-flow mainly did it as ceremony, without realizing or checking on any of the effects it promises. This leads either to incredible process waste if you try to run a development strategy that’s in opposition to git-flow (as laid out in the post) or people learning to sidestep the process, as it doesn’t matter anyways.

    1. 17

      After working at Bitbucket for a number of years, I tend to have opinions on Git workflows and best practices. While some of these are good points, they also gloss over details.

      Gitflow abandons rebasing

      Yes, by design. Or rather, rebasing was considered a non-starter. Git doesn’t store what branch a commit came from, so the only way to track this is either fully squashing commits (which I’m generally not a fan of because you can lose history) or leaving the branches (and explicit merge commits) in. I think it’s good to squash commits while on a feature branch to clean up history, but I’m not a fan of doing that once it’s merged in. And that can also cause issues down the road if someone had to base code off one of your feature branches (something that’s a WIP).

      Gitflow makes Continuous Delivery Improbable

      I’m sorry, but this simply isn’t true. For a web service, long lived branches represent environments. As an example, with develop and master you could have those both auto-deploy to 2 environments, one for internal usage and testing, one that’s considered stable. Alternatively, if you’re releasing versioned software you can configure your CI to automatically build and release each tag.

      One alternative method is develop (for semi-volatile code), stable/integration (for stuff ready for release, usually directly merged from develop), and master (for production). Having a rolling release branch can make this easier to manage overall.

      Gitflow is impossible to work with in multiple repositories

      If long-lived branches are orthogonal to environments (as described in CD above), this can work fine. Each repo can point to a long-lived branch on another repo.

      Gitflow is impossible to work with in a monorepo as well

      This is probably the most valid point here. However, if you have a monorepo, you’re generally moving away from the “standard” workflows anyway.

      Ok, so my team shouldn’t use gitflow. What should we use?

      While git flow can be a good starting point, it doesn’t work for everyone. As the author mentioned, both rebasing and monorepos don’t work well with git flow. For these, you’ll probably need to design your own workflow. For software that doesn’t need to have multiple versions active at one time, you can simplify the versioning and focus on long lived branches for different environments.

      I agree with the premise that git flow doesn’t work for everyone, but it seems like this article focuses on things that haven’t worked for the author and declares them “impossible”, which I don’t agree with. There are simpler workflows that generally work, but they’re meant to solve different problems.

      On a side note, I’m very happy this article wasn’t called “Git Flow considered harmful”.

        1. 3

          Yes, with exception that instead of “version branches” create branch for release, prepare it there, tag release, then merge it to the master and call it a day, no develop/master split and having each commit on master tagged.

          1. 6

            Using tags only for web-only/evergreen software can work, but branched versions are often a must-have for desktop work. If a security issue is discovered with version 1.3.0 through 1.6.7, you may need to release 1.3.1, 1.4.6, and 1.5.3 alongside 1.6.8. In that world, it’s best to have 1.3, 1.4, 1.5, and 1.6 branches, where e.g. 1.4.5 is a tag on the 1.4 branch. In this scenario, you’d want to fix the bug in the 1.3 branch and cut a tag, then merge that into the 1.4 branch and cut a tag, then merge into the 1.5 branch and cut a tag, etc. That workflow’s not doable using just tags.

            Again, for evergreen/web-only software, I’m with you, but version branches absolutely have their place.

            1. 3

              But you know that you can create commit on detached head? You do not need branch for that? And even then you can create temporary branch for that particular fix, ex.:

              git checkout -b hotfix/space-overheating v1.3.0

              And after that you can create new tag 1.3.1 that will not be reachable from master (as you would do anyway) and you can remove temporary branch.

              1. 1

                I would not say “must-have”, I believe google chrome is doing just fine with a continuous release model, even though it is “desktop work”: https://medium.com/@aboodman/in-march-2011-i-drafted-an-article-explaining-how-the-team-responsible-for-google-chrome-ships-c479ba623a1b

                1. 4

                  I’m aware of that, which is why I also very clearly, twice, called out evergreen software as also not needing branched versions.

                  1. 1

                    I wasn’t aware of the term “evergreen software” is there a definition around somewhere?

                    1. 1

                      I’ve heard it used informally to refer to, for example, an API that is continously updated without a specific version number. Breaking changes are communicated by other channels, such as websites for developers.

                  2. 2

                    Google has the ability to say ‘this software is only supported for 6 weeks and then you must update’. 99% of other software vendors do not have that ability.

                    1. 3

                      Software Users have been burned by vendors too often, that is why they demand “bugfix releases”, they do not trust devs to deliver a feature upgrade without regressions.

                      1. 2

                        I mean it’s not like people trust Google to deliver a feature upgrade without regressions. They just don’t really get any say in it. Google’s web browser isn’t a product.

              2. 2

                I don’t understand what branch by abstraction is about. From the web site, it seems like a development strategy, rather than a way to use version control.

                1. 1

                  They go hand in hand:

                  • Don’t do long lived (>1 week) branches, especially don’t do them to build large new features.

                  • Instead, use a well-conceived feature-flag system to turn off in-progress code that you merge to master.

                  It’s a negative suggestion, not a complete version control strategy.

              3. 14

                Unhelpful article. Complains about gitflow, makes no real recommendations beyond “ask questions of your team”.

                1. 24

                  The whole point of the article is to advocate spending significant time & effort on original thinking about what works for you and your group, and why - instead of copying a neatly-documented workflow you found on the internet.

                  Given that, what other kind of recommendations could it possibly make?

                  (nb: I have a preference but no strong opinions on the topic - deriving your own workflow is actually pretty expensive and you might want to spend those cycles elsewhere, but I’ve had good yield from the exercise in one team).

                  1. 4

                    encouraging your team to communicate is great! if that was the main point, then the article should have been titled “talk with your team” and been filled with techniques for better communication. but the article i read mainly complained about a git pattern that lots of people find useful.

                    1. 4

                      Why must every article critical of a topic take the paternal role of telling you what to do instead? Can’t you exercise the critical thinking yourself? There are likely hundreds of articles out there, some linked in this thread, about alternative version control workflows, and they’re not too hard to find. Flagged your reply series as “troll” because it adds nothing to the conversation except “the author didn’t write enough and so I didn’t like the article”.

                      1. 4

                        The point isn’t simply to communicate, the point is to critically think about the workflow. The blog post contains the author’s critical thoughts on the workflow, and encourages people to think critically about their own workflows. Asking questions of one’s team is really a means to that end rather than the end itself.

                        1. 0

                          Its easy to complain about something that’s causing you pain. Its harder and more useful to look for a better course of action that can alleviate the suffering. My problem with the article is that it complains alot about problems but talks very little about solutions.

                          (The problems described are real, I’ve experienced them myself)

                          1. 8

                            While I generally agree with this, it is very important to see what is being criticised.

                            git-flow is a heavy process that has to argue for its value at every corner. The “other option” is using unstructured branching and PRs to master.

                            It’s a general problem that processes are argued for by pointing out the absence of a replacement. Some processes can be removed without replacement.

                            1. 1

                              I disagree strongly with the idea that GitHub-style pull requests should ever be considered the ‘default’ workflow with git.

                              1. 1

                                I neither suggested one or mind which PR style you use.

                                1. 1

                                  Well I extend that to all pull requests that aren’t git-pull-request. Sending patches is the default: it’s what git was designed around.

                                2. 1

                                  What’s your thinking here? Or what are you advocating against? Can you point me towards any resources or your own thoughts on this?

                                3. 1

                                  That’s a useful point, which would have been helpful if included in and expanded upon in the article. (Unless I missed it somehow?)

                                  1. 4

                                    On that level, I definitely agree with you.

                                    But the article in the end does make a case for reflection and inspecting your process. I think it’s a bit much to ask for what is essentially an essay to cover all the corners.

                        2. 2

                          Please see my answer above for one very simple suggested workflow I’ve seen work well.

                          I think you may be going too far by labeling this ’unhelpful” because there is in fact no one size fits all solution, and the author is right about that, but I agree it could certainly be more helpful by offering some potential starting points for a solution.

                        3. 4

                          A thousand times yes.

                          Every repo that is following gitflow comes with a mental overhead for me.

                          Companies with lots of small repos, each and every following strict gitflow? A nightmare.

                          It just takes longer when I try to get something integrated. Every. Single. Time.

                          master is where the action should be. Just freaking rebase and push your commits to master and be done with it.

                          Unsure? Need somebody to look over it? A longer story? Use bloody branches.

                          Wanna do stable releases? Use a branch, tags, cherry-pick as much as you want.

                          Want to know what people are working on? just git branch -a and you see descriptive names not cryptic numbers.

                          I don’t know, maybe it’s just me but gitflow and me just doesn’t work. Pardon my ranting.

                          1. 3

                            Your comment just sounds like it’s describing git-flow to me, but with ‘develop’ renamed to ‘master’ and ‘master’ renamed to ‘stable’ (as they should always have been).

                            Just freaking rebase and push your commits to master and be done with it.

                            The diagram in the blog post shows commits made directly to ‘develop’. It doesn’t mandate that everything goes through a feature branch.

                            Unsure? Need somebody to look over it? A longer story? Use bloody branches.

                            Yes, those are feature branches.

                            Wanna do stable releases? Use a branch, tags, cherry-pick as much as you want.

                            That’s just what they do? A branch and tags.

                            Want to know what people are working on? just git branch -a and you see descriptive names not cryptic numbers.

                            git flow has nothing to do with how you name your branches except for the prefixes. Nobody is forcing you to name all your branches feature/ABCD-1234 instead of feature/beginner-mode.

                            I do think gitflow is a bit odd because in web-style development where you only want a single released version, you don’t really need their ‘master’ branch, and in desktop-style development you should probably do away with their ‘master’ and just keep the release/ branches around so you can do 1.3.17, 1.4.7, 1.5.3 and 1.6.1 hotfixes from those branches.

                            1. 2

                              You’re right (partially at least). I think the key difference between what I described and what gitflow ordains is that in gitflow you have to always do a branch. And in gitflow you do not rebase and you do not directly push to master.

                              1. 1

                                As I said:

                                The diagram in the blog post shows commits made directly to ‘develop’. It doesn’t mandate that everything goes through a feature branch.

                                So I disagree with your claim that you do not rebase and you do not directly push to master (or as they call it ‘develop’). Feature branches as presented in the article are only for the development of new features, not minor changes.

                                1. 1

                                  So I disagree with your claim that you do not rebase and you do not directly push to master (or as they call it ‘develop’). Feature branches as presented in the article are only for the development of new features, not minor changes.

                                  That is exactly my point. You do it on “develop” and not on master. gitflow doesn’t call master “develop”, as you say. gitflow just added a completely new branch for integration of changes and called it “develop”. In gitflow master, degrades to something (I don’t understand why, though) that kind of follows “develop” but feels like a last-resort-integration-branch-before-we-do-a-release kind of thing.

                                  And that is exactly the reason why I happen to dislike gitflow. It is needlessly complicated and seems not well thought through.

                                  This might stem from the early days of git’s success when people adopted it (including me) but didn’t understand git well enough so they looked for “processes” or rather “workflows” to help them and their co-workers through this whole mess of trees of branches and merges.

                                  But today? I think we really don’t need this anymore.

                          2. 4

                            I’ve quite happily used (slighty modified) versions of git flow in several orgs. It is particularly useful when you have a dedicated testing team, who need a stable base to test on. And it’s really not complicated in practice.

                            From the article:

                            The entire branching model is predicated off a predictable, long term release cycle; not off releasing new code every few minutes or hours.

                            This, I think, is the crux of the issue. I don’t want to deploy to prod every few hours. My users definitely don’t want me to, either. Sure you could argue that automated testing should give you complete confidence in your changes, but for many systems either a) the coverage isn’t good enough or b) even if it were, the business doesn’t have the appetite for releasing without a human sanity-checking them.

                            1. 4

                              [Side note: I was a release engineer for 1.5 decades so I have Opinions on this stuff. If you love Gitflow, I am not attacking you. Please consider dropping me a message if you feel I’m out of line and I’ll modify the post.]

                              This is a superb article and I agree with pretty much 100% of what the author states. I just want to add a tiny comment to:

                              Ok, so my team shouldn’t use gitflow. What should we use?

                              The author rightly says that you should work it out with your team and come up with the minimal strategy that works for your needs.

                              However, I would suggest that a minimal workflow I’ve seen used very successfully in a number of teams might be a good starting point for the discussion.

                              It comes down to this:

                              • Developers work on “bug branches”. The branches are named based on the issue ID from your bug tracker.
                              • Bugs that end up taking a long time to complete should rebase from master on the regular to avoid the “One giant horrid merge” problem.
                              • After the bug has been resolved and CI passes on that branch (Your CI system should make this easy. If it doesn’t there HAS to be a plugin or something. This is a very common workflow) the developer merges the branch back to mainline / master and then deletes the branch at origin.

                              This is by no means a one size fits all solution, but I’ve seen it work well with small to moderate teams, and sometimes I think giving people at least a starting point for their workflow analysis can be very helpful.

                              1. 3

                                Developers work on “bug branches”. The branches are named based on the issue ID from your bug tracker.

                                Pleeeease not just the bug ID! A branch called ABC-1234-beginner-mode-feature is so much easier to work with than ABC-1234 and if you have autocomplete you never have to type the name because it should be unique given the number.

                                1. 2

                                  Why is that so much easier to work with? Why shouldn’t all the descriptive information go in the issue tracker?

                                  I personally find it kind of frustrating if I have to go through the naming exercise every time I create a work branch, but maybe if I understood the value prop I could see it better?

                                  1. 3

                                    It’s not really a naming exercise if the ticket has a title. In JIRA it’d be something like “ABC-1234 Beginner mode” or “ABC-1111 Settings reset doesn’t reset UI settings”. So then you name the branch ABC-1234-beginner-mode or ABC-1111-fix-ui-settings-reset. It’s pretty mechanical really.

                                    But the reason for it is that when looking at a list of branches, having just the numbers makes them basically meaningless. I want to know what the branches actually represent, not just see a meaningless contextless number.

                                  2. 1

                                    Yes! We use something like US-1999-UpdateDateFormatForOldData. US is for user story.

                                2. 3

                                  The article ends by saying they can’t tell you what to do instead.

                                  My suggestion: use gitflow with only two long lived branches master and develop.

                                  What airflow encourages is to not have long running development on parallel diverging branches. This is an important thing to keep in mind.

                                  1. 2

                                    Can you please explain what value gitflow brings to your suggestion over simply developing on these two branches with plain vanilla git?

                                    1. 1

                                      Hi @feoh

                                      What would you consider plan vanilla git? It maybe that what I refer to as git flow is what you call vanilla git?

                                      To me the key things are having an unstable (develop) branch and a stable release (master) branch. Urgent fixes are done on a hotfix like branch and then quickly merged to master and other branches. New features and non-urgent bug fixes are done in develop or specialized feature branches.

                                      Feature branches become useful when you have to spend a lot of time on a feature and you don’t want that getting into develop. Stuff in develop is almost ready to be put into a release master but I want to hedge a little bit.

                                      Also, for the kind of thing I do, I now am interested in trying out the suggestion somewhere else in this thread of using just a master + short lived feature branches.

                                      Mostly, I end up mirroring develop on master. develop tends to be the branch where all the good stuff is done, but I’m kind of hesitant to have it on master just in case I find some un caught bug. I guess I treat develop as “next release candidate”, which can also be a short lived branch.

                                      I don’t do a lot of rebasing simply because I am not worried about having a lot of commits, or having a commit look very neat. For some that may be important. I like having small commits.

                                      It is during release that I go through all the commits and make a summary of what the new release brings.

                                      1. [Comment removed by author]

                                        1. 1

                                          defined in this blog post

                                          Interesting, what part of that diagram am I missing in my description above?

                                          1. 2

                                            Quite right. I was the one misreading/misunderstanding. I’d been conflating ‘git flow’ the methodology with gitflow the git extension software.

                                            That’s why I mentioned “plain vanilla git”.

                                            Your proposed workflow of an unstable developer branch and a stable release one is perfectly reasonable if it works for you and your team!

                                  2. 3

                                    The main workflow we use: every feature or fix is initially worked on in its own branch that diverges directly from master.

                                    A branch is ready to merge when ci passes, commits represent isolated change sets, commit messages are descriptive and peer reviewers are satisfied.

                                    In the peer review process, adapting earlier commits in the feature branch after pushing and receiving feedback is encouraged. And thus force pushing is common practice.

                                    Then 1) rebase to master and 2) merge back to master without fast forwarding. A github bot makes sure that only one merge can happen at any time and that a branch is rebased to master one last time before it is merged. This results in a very simple, linear graph, but all commits from a single feature/fix branch stay visually grouped.

                                    EDIT: The master branch represents a big future release of the product, which is not the public version. The latest public version and legacy versions are in their own branches, and hotfixes follow the same pattern as in master, except that the fix branches derive from the version branch.

                                    Changes on master can be cherry-picked into the public versions branches if needed. Hotfixes on the public version branch are merged into master on a weekly basis as a single, squashed commit.

                                    1. 3

                                      I can highly recommend to consider using something like https://bors.tech for this workflow. It makes sure the merge commits are meaningful (“merges this branch, ticket here…”) and has a merge model that makes it frictionless.

                                      1. 1

                                        This is great to see in the wild. My team had to build the merge queue feature and it was a huge pain to orchestrate and keep devs happy.

                                        1. 1

                                          It’s an extraction of what Rust uses for rust-lang/rust.

                                      2. 1
                                        1. rebase to master and 2) merge back to master without fast forwarding.

                                        This results in a very simple, linear graph,

                                        If every commit has exactly one parent, what difference does it make if you’re not fast forwarding? You get, what, a … merge commit that has just one parent and no content?

                                        1. 2

                                          The merge commit can hold quite a lot of metadata - who reviewed it, where can I find the documentation for what was merged (Issue, PR number), etc. Merge commits are only junk if you don’t care about editing them.

                                          1. 2

                                            merge commit that has just one parent and no content?

                                            Exactly. This way, the information of which commits were done together within a branch is not lost. In our case the merge commit message usually holds the description of the pull request.

                                            1. 1

                                              oh, I just put that stuff in an annotated tag. The commits you’re talking about are just the commits between the two tags. Then I use git diff thing-v0.3.2 thing-v0.3.3 or git log thing-v0.3.2..thing-v0.3.3. The urls you get out of bitbucket or github then have the tag names instead of commit hashes, so the urls actually describe whats on the page. Um, I’m pretty sure every benefit that people have mentioned works the same with annotated tags?

                                              1. 1

                                                That seems like a good approach too. The only thing is that you don’t get is the nice graph in a GUI git client: one line representing master and single offsprings getting grouped back in.

                                            2. 1

                                              Merges with two parents, but one of the parents is a descendant of the other.

                                          2. 2

                                            Okay, I’m going to say it. YAGNI. YAGN complex git workflows. Solve your version control problems like an engineer. Your product almost certainly does not need this stuff. Also git isn’t hard. Branch when you want independence.

                                            1. 2

                                              Is there a survey article describing popular workflows and their good/bad points?

                                              1. 2

                                                I can see a hotfix and stable branch with semantic versioning, only if you have a released/shippable product that people can self-host. It’s important in those situations to be able to backport hotfixes/security bugs onto older releases.

                                                That being said, semantic tagging for internal apps, internal customer facing web apps or anything else is stupid. You only need two version numbers: major.minor. There is no purpose in a patch release (unless maybe you have different customers all running different versions of your app maybe?). I’ve heard one developer even say you should just have 1 incrementing version number for internal apps. I can still see the argument for major/minor, but three numbers and the full git-flow branch pattern mentioned is only necessary for things you ship past your company boundary.