Hacker News new | past | comments | ask | show | jobs | submit login

In my opinion the problem with GitFlow and a lot of other git workflows is you end up holding a bunch of state inside of your git branches which is hard to decipher, complicated to manage, creates work for people ( with merge conflicts, and managing feature branches that need to be merged ), and is capable of losing progress.

My solution: USE FEATURE FLAGS. Keep the list of features and refactors you want deployed in a format that is easy to audit and reason about.

I like the Microsoft branching strategy: https://docs.microsoft.com/en-us/azure/devops/repos/git/git-...

Basically:

* Create feature branches.

* Merge into master when the feature is done. For long lived branches: Don't keep them around. Merge them into master and put them behind a feature flag.

* Deploy to environments using release branches.

* USE FEATURE FLAGS. Do not hold state in your github repo/branch merge status. Do not control features and refactors inside of your git branches, only merging the code you want to be deployed. Instead, put them behind feature flags and activate them using code.

There is a good book on the topic of feature flags titled "Effective Feature Management" that is a good overview. Feature flags do not have to only protect features. You can put refactors behind feature flags as well, or really anything.




Thanks for the feature branch book recommendation.

Overall, feature branches work well as an approach for relatively modern systems. I once worked on a distributed, multi-process system from the 90s that powered more than 40 factories across the world monitoring and steering production of goods. Every factory could decide whether to upgrade and to which version. Each upgrade was a separate project, which had to go through a public offering and deploy at times when the factory was not operating.

The inability of central IT to exercise influence on the factories to upgrade (due to the rollout costs) and reduce the number of parallel versions, caused a multitude of support branches to be maintained for this system. We maintained at least 6 active branches in parallel, backporting bugfixes across branches and being able to release hotfixes at any point in time for these versions. Although another VCS was used for managing source code and build artifacts, for development, we have successfully managed to use git with multiple, long-lived support branches and merge fixes across these, like in gitflow.


I've never understood how Feature Flags can be used like that. For example say I have a button component that needs to be refactored and it used in hundred of places throughout the codebase. How can I use feature flags to prevent a long running branch? (Serious question :))

Do I keep both implementations around and everywhere a button is used switch on a flag, that seems quite messy, and I have to go and delete the switches on the flag everywhere when I'm finished. Or I could abstract that out into a function or use dependency injection to choose the right button, but that just seems to be adding another layer of complication, that some future dev is going to wonder why exists when there is only one implementation of the button.

Compared to having a long running branch that I periodically merge the main branch into to keep up to date with the current development without impacting the code that is due to released in 2 days (as it is every 2 weeks)


Regarding your button question:

You do need some sort of seam at the point of use so that the feature flag logic can be hidden behind a lookup function. For example in Rails you might include your button code via a partial template. You could use a view helper to provide the name of the partial and that helper could respond with different names depending on the feature flag:

    <%= render partial: primary_button %>

    def primary_button
      feature_flag_enabled ? "new_button" : "button"
    end
Obviously the particulars are going to be different in different frameworks.


This is all covered in the book I recommended! :)

For the button:

I would say abstracting it out into a function or using dependency injection, and having a centralized switch statement is the way to go. I don't see why you would need to break your interface for most refactors, and if you DO have to, that means your code had a major issue anyway.

Additionally, how is the "just using git for feature management" alternative better? With a feature flag you can enable and disable the feature easily without a deployment. With git, you have to do a revert/rollback/whatever to ship a fix.

I struggle to think of an effective way to reuse a button component over and over again without using a function or dependency injection. If you are speaking of react: Those are functions. That HTML you are using is actually just some syntactical sugar around functions.

You would not keep both versions of the button around permanently. You would merge the branch into your master branch, and enable the feature for the desired environments. When all environments are using the new refactor, and it has been verified to be working, you open a pull request to delete the old version of the refactor and purge the feature flag.

"Well, that is still complicated!" That is true, there is still process around managing features with feature flags. The benefit is that feature flags are easy to grok. It is an if statement. Your application state is no longer contained in an interminably long git log. Instead, it can be determined by checking your feature flag configuration.

> Compared to having a long running branch that I periodically merge the main branch into to keep up to date with the current development without impacting the code that is due to released in 2 days (as it is every 2 weeks)

This becomes laborious over time. If you have many people working on a codebase, the feature branch will constantly break and you will have to go back in fix it.

What if someone has to revert something on the main branch that you have merged with your feature branch? You are now in merge-hell and you have to spend a bunch of time figuring out how to make your branch and the fucked-up master branch have the proper code in them.

What if someone on your team does a hard-reset to the master branch? ( Well just don't do that! Oh, sorry, I didn't realize you were the tech lead for your place of business, and get to decide how everyone else solves their various problems. ) Now your branch is out of date and you have to revert commits and fuck around with your feature branch, and HOPE that you actually unfuck your version history properly.

Look at the alternative: You uncheck a box on a web GUI, the bug is contained, you go in and fix it, deploy it, and re-enable the feature.

Your "what if we just don't worry about it, and not solve the problem" suggestion here does exactly that: Ignores the problem we are all experiencing, and then does NOTHING to solve it.


I've used nvie-like gitflow strategies without significant issues.

One of the things that I like about the strategy is that it works well for code-like things and for things like handbooks/documentation sets built with e.g. Hugo+docdock. Authors branch, work, PR, PR gets vetted for accuracy/policital-correctness/whatever and then gets merged.

Anyone have any experience using feature flags with static web site generators?




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: