Live data from Hacker News

A successful Git branching model (2010)

nvie.com

31–40 of 121 posts

Re: A successful Git branching model (2010)

#31

Earlier quoted context omitted.

Feature flags are a nice idea, but nobody outside of Facebook seems to be embracing them. The tooling just isn't there. Some concrete questions: - How do you prevent your codebase from becoming if-statement spaghetti? - How do you prevent new features from being leaked to the user? They'll see the new features in the front end source code. At many companies this isn't an acceptable tradeoff. So do you preprocess the…

> Feature flags are a nice idea, but nobody outside of Facebook seems to be embracing them I worked at Etsy from early 2012 to late 2015 and I used feature flags every day I was there. > How do you prevent your codebase from becoming if-statement spaghetti? You remove the feature flag checking code when you turn off or turn on the feature. It's an extra deploy, but it needs to be part of the prod/eng process. This is…

You remove the feature flag checking code when you turn off or turn on the feature. It's an extra deploy, but it needs to be part of the prod/eng process. This is the most salient issue of feature flagging in my experience and something you need to get ahead of from the get-go.

I don't understand. I was asking about the development source code, not the code delivered to the user. The dev source code isn't stripped of if-statements, right? That's where the feature flag toggling lives. But then it seems like it's easy to devolve into spaghetti.

You branch at the server/request level, not the client level, so there is no set of features that gets displayed, it's just what the server returns.

Ok, but how? I'm not playing dumb. Assume an express server. You want to put a feature flag into your codebase. What is step #1 (and #2 and ... #N) to achieve this?

I looked up LaunchDarkly. $299/mo for basic team support. Uhh... That's almost the cost of WeWork office space.

Are feature flags really so nascent that there isn't a FOSS solution for it?

Re: A successful Git branching model (2010)

#32
post #15

I've got a much nicer branching model- try not to have one. Everyone works off master, and you aren't allowed to check in code that won't run in production. Hide unfinished features behind feature flags, and never merge/push a change that won't pass tests/CI. The chaos of huge feature merges (a key source of bugs I've experienced) is minimized. You deploy fixes hourly, not weekly (or later monthly when it just won't…

I think from the perspective of the central repository, this is a sane approach. Locally though, you should still be routinely using (short-lived) feature branches. Working directly off master on your local machine can make things annoying / complicated when you need to move away from your work for a moment (say to fix a bug) and don't have a good representation of "what's currently on production".

Also, I think this approach necessitates that you have some form of continuous deployment, or strong assurances that master is almost always on production. If, for example, you have a fixed 2-week cycle for production releases, "just work off master" will be a source of pain when you inevitably have to fix a bug on production without rolling out the other commits that are there for the "next release". That might not be an optimal way of developing, but it's about more than just how you use git - it's really more of a delivery question.

Re: A successful Git branching model (2010)

#33
post #25

Earlier quoted context omitted.

My bad, I was going to edit my comment to be less coy and more constructive, but I'll just continue here. Even though I always advocate rebasing, I also think that WIP commits should not reach master as-is. We are actually using Phabricator with my current team, and they have a really nice opinionated way of doing development. All dev happens usually in (really short-lived) task branches, but once they have gone thro…

Nah, I agree. Solid argument. So, all dev happens in feature branches, and they're integrated into master as squash commits. That just leaves two questions: - Use release branches? Or just take the shotgun approach of "everything in master has to be working all the time"? - When a problem inevitably pops up and you have to roll back, how do you kill just one commit? It's already been pushed to the repo, so a hard res…

It would be optimal if the team can have the discipline to never commit broken stuff, and we could live with "everything in master must be working all the time".

If that does not work in reality, or breaking it would simply cost too much (because mistakes will happen), I'd use release branch or use git tag to mark versions with "no really, this one really truly actually works in every way".

For your second point, see 'git revert'! It does exactly that, i.e. picks a commit and effectively removes it from a branch by making its "mirror commit". The other way is, of course, just deploying an actual fix asap, git revert is just for when fixing the problem is for some reason or other slow and master must be unbroken immediately.

Re: A successful Git branching model (2010)

#34

This was very much valid before the docker workflows came to happen. Now maintaining two mainline branches forces you to break "don't build a container per environment" cardinal rule. Trunk based development should be the go-to repository strategy for dockerized apps.

What's the purpose of that rule?

Re: A successful Git branching model (2010)

#35
post #21

Earlier quoted context omitted.

This is called trunk-based development, and it is the only development model that scales to thousands of engineers in one repository.

While I do like this approach, it can cause some pains though. It's often a race to get your (approved) merge- or pull- request in. If you miss out, then you rebase, and try again. Perhaps if your pipeline is super fast, it isn't an issue. Another issue is that there still needs to be coordination outside of version control/CI pipeline to ensure that things are put in the 'right order', for the times when that is imp…

Developers rarely push directly to master in large organizations. Instead, a CI pipeline verifies your code passes tests and then pushes to master.

There are trade-offs here around "semantic merge conflicts", but they happen rarely in practice. To avoid making this disruptive to developers, you can have another branch that marks the latest commit to pass tests. This branch should always be an ancestor of master and should only be updated by your CI pipeline.

Re: A successful Git branching model (2010)

#36

Earlier quoted context omitted.

> Feature flags are a nice idea, but nobody outside of Facebook seems to be embracing them I worked at Etsy from early 2012 to late 2015 and I used feature flags every day I was there. > How do you prevent your codebase from becoming if-statement spaghetti? You remove the feature flag checking code when you turn off or turn on the feature. It's an extra deploy, but it needs to be part of the prod/eng process. This is…

You remove the feature flag checking code when you turn off or turn on the feature. It's an extra deploy, but it needs to be part of the prod/eng process. This is the most salient issue of feature flagging in my experience and something you need to get ahead of from the get-go. I don't understand. I was asking about the development source code, not the code delivered to the user. The dev source code isn't stripped of…

The expectation of a bunch of weird branches making everything confusing (I had that too) ends up being unfounded. You typically only see a few places with branching logic, and people usually draw attention to it being branching logic for a feature or experiment.

How and where you branch really depends on the feature. If you're A/B testing a button color, you'll deploy a different strategy than if you're trying to introduce new logic with minimal regressions. But you can plan out your strategy in both cases to minimize leaking information and disrupting user experience (and you should).

>Ok, but how? I'm not playing dumb. Assume an express server. You want to put a feature flag into your codebase. What is step #1 (and #2 and ... #N) to achieve this?

The general flow is: get status of features from source of truth. Check current feature flag's status. Do something based on that status. You can make it as complicated or simple as you like. You can have a global boolean flag for all features where it's always either true or false. You can have different flags for different users, you can have certain percentages of users have different values for flags. But it all starts from getting the value of a flag for this current request from the source of truth.

Let's say you're writing a crud app on an express server that communicates via http to a database service. Your database service is rolling out v5 of their api, and they're at the last stages of their beta so they're pretty confident. You decide you want to test it by routing half of all the traffic to your crud app through v5 and the other half as normal through v4. You could lay out your code in several ways, and you'll have to figure out what works best for your model and your team.

Let's assume you have a feature service you query on every request (maybe it's express middleware) to see if an experiment is enabled for the current user, and you've queried your current user against api v5, and you have a boolean variable indicating whether to show v5 or v4 and it's used in a route handler for your home route.

You could change the url you hit based on the state of the experiment, provided the interface to the api is the same.

    const routeUrl = '/api/v4/home/'
    if (featureIsEnabled) {
      routeUrl = '/api/v5/home/'
    }
Inside the route home route handler you could have an if/case statement that did a completely different request and response.

    if (featureIsEnabled) {
      return queryV5('home').then(respondToV5).catch(handleV5);
    } else {
      return queryV4('home').then(respondToV4).catch(handleV4);
    }
You can also do this on the front end - a lot of feature / experiment services have front-end libraries. I prefer to do it server side.

Re: A successful Git branching model (2010)

#37
post #35

Earlier quoted context omitted.

While I do like this approach, it can cause some pains though. It's often a race to get your (approved) merge- or pull- request in. If you miss out, then you rebase, and try again. Perhaps if your pipeline is super fast, it isn't an issue. Another issue is that there still needs to be coordination outside of version control/CI pipeline to ensure that things are put in the 'right order', for the times when that is imp…

Developers rarely push directly to master in large organizations. Instead, a CI pipeline verifies your code passes tests and then pushes to master. There are trade-offs here around "semantic merge conflicts", but they happen rarely in practice. To avoid making this disruptive to developers, you can have another branch that marks the latest commit to pass tests. This branch should always be an ancestor of master and s…

> Developers rarely push directly to master in large organizations. Instead, a CI pipeline verifies your code passes tests and then pushes to master.

Yup, that's what I was referring to with my 'merge- and pull- request' line.

Interesting idea about having another branch.

Re: A successful Git branching model (2010)

#38
post #18

Earlier quoted context omitted.

I was researching some of this a few weeks ago, and there are many posts about tags being a bad idea. The arguments are that they have to be maintained separately and they lack context. But yes, master branch master race. Also related: "What are the problems with 'a successful Git branching model'?" https://barro.github.io/2016/02/a-succesful-git-branching-mo... Speaking of bad ideas, anyone want to weigh in on merge…

I always advocate workflows where merges never happen. To me, the 'git log' of a master branch is like a history book about the repository. When you read through it, it should give you answers to the questions "what was changed, why, and when" in as clear format as possible. Now, I've read most of the arguments trying to show that merges are the way to do just this, instead of rewriting history with interactive rebas…

It looks more like merge. Chinese history and European history merged around 1200, and then again a few centuries later. American history and European history merged around 900 and then again in 1492.

But, why not both? Using interactive rebase lets you keep a clean and bisectable history made of small commits. The developer every now and then can also rebase to master and ensure that all commits pass the tests (and perhaps write more tests based on what happened in the meanwhile on the master branch).

However, when CI runs, features are included in master with a merge commit, so that the occasional semantic merge conflict will bisect exactly to the merge commit and the developer of the feature isn't blamed incorrectly.

Re: A successful Git branching model (2010)

#39
post #9
post #3

The advice here given to avoid using "master" branch for development, and advice to create non-default branch named "develop" (or variations thereof) is quite harmful. If you must have a "release" branch or "stable" branch, ok, go for it, but leave the "master" for developing. Why? Strive to have sane defaults. Frankly, the idea that somebody must check out some extra special branch after cloning repo in order to sta…

I find the idea that master is the default is exactly why it should not be the development branch. For open-source software, that's what people download and try to build -- it should always strive to be production ready.

People should be downloading actual releases. This could be release archives, or release tags.

Version control is not primarily for consumption of releases, it's for participation in development, and I think the branching strategy should reflect that. Having the current development state be the default branch is entirely suitable for this purpose.

I've always found the use of "develop" vs "master" quite jarring, and not even that helpful for an end user. master can change on a whim, while using actual release tags gives you something stable.

Re: A successful Git branching model (2010)

#40

Earlier quoted context omitted.

You remove the feature flag checking code when you turn off or turn on the feature. It's an extra deploy, but it needs to be part of the prod/eng process. This is the most salient issue of feature flagging in my experience and something you need to get ahead of from the get-go. I don't understand. I was asking about the development source code, not the code delivered to the user. The dev source code isn't stripped of…

The expectation of a bunch of weird branches making everything confusing (I had that too) ends up being unfounded. You typically only see a few places with branching logic, and people usually draw attention to it being branching logic for a feature or experiment. How and where you branch really depends on the feature. If you're A/B testing a button color, you'll deploy a different strategy than if you're trying to in…

Using properly interfaces and implementations with an IoC container solves this problem without causing any messy if-else leakage throughout the code.
Post reply on HN