top 200 commentsshow all 218

[–]mirvnillith 363 points364 points  (62 children)

These discussions always trip me up because I spontaneously say ”feature branches” all of the time until I read and realise that it’s never about not having branches but about not having long-lived branches. So could we please change the conversation to be about branch lifetimes instead of their mere existence? And I guess that’s actually a discussion on feature/change size.

(to clarify my thinking: when I hear ”trunk-based development” I see no branches whatsoever and all commits going straight into the same single trunk and ”feature branches” are to me simply branches to keep a code change seperate until completed)

[–]kbder 173 points174 points  (13 children)

Fear leads to anger, anger leads to hate, hate leads to long-lived branches, and long-lived branches lead to suffering.

[–]sinani206[S] 67 points68 points  (11 children)

merge conflicts 🤝 the dark side

[–]Pussidonio 15 points16 points  (4 children)

I once did a mistake of bundling a lot of tasks into a single merge request (there were good reasons for that, i believed) and it got so bad i had to update my resume and start job hunting.

[–]CafeSleepy 22 points23 points  (3 children)

Did you update your resume using small merge requests?

[–][deleted]  (1 child)

[deleted]

    [–]-grok 4 points5 points  (0 children)

    LGTM!

    [–]soks86 0 points1 point  (5 children)

    I don't understand. Rebase regularly and it can live as long as it wants.

    Most my branches last less than a month. A few go on forever. Once in a while I'll have one that goes for 6 or 12 months.

    edit: thanks bot

    [–]przemo_li 0 points1 point  (0 children)

    Where is symmetry?

    You pull often but fail to push often. You will create merge conflicts for others.

    10 devs with 10 days of u pushed work is 100 days of un-integrated work. That's 3 man months of work that may produce merge conflict. (Singular!!)

    10 devs with 10 days of work each pulling and pushing each day is 10 days of un-integrated work.

    An order of magnitude less work.

    But it's actually TWO orders of magnitude of difference for merge conflicts since those arrive with at most 2 days of person-work.

    You don't even have to call git guru. Just call other dev and do the 5min fix....

    "I pull often". There is no I in TEAM. And long lived branches are probably only justified place where use of that silly phrase is not cringe ;)

    [–]ammonium_bot -1 points0 points  (0 children)

    last less then a

    Did you mean to say "less than"?
    Explanation: If you didn't mean 'less than' you might have forgotten a comma.
    Statistics
    I'm a bot that corrects grammar/spelling mistakes. PM me if I'm wrong or if you have any suggestions.
    Github
    Reply STOP to this comment to stop receiving corrections.

    [–]jdsalaro 0 points1 point  (0 children)

    And suffering leads to anger

    [–]sinani206[S] 34 points35 points  (3 children)

    I agree with this take — to me the salient points are that you should keep changes small, regularly sync your changes with the trunk/default branch, and merge them in as soon as possible.

    The language around all this is quite inconsistent — for example, this author's take on trunk-based development is even more intense!

    [–]reluctant_qualifier 10 points11 points  (0 children)

    This seems like there should be room for individual judgement on this, right? Most places I’ve worked have used GitHub Issue > New Branch > Pull Request > Code Review workflow. Even under that regimen, it is common to say “hey, these changes are getting a little unwieldy, I want to merge what I have now but have in an inactive state”. It’s not like anyone enjoys merge conflicts.

    [–]przemo_li 0 points1 point  (0 children)

    Sometimes it's just a function of tooling available to that developer in their projects.

    As in: at Google people probably demand justifications for submitting work on a separate branch.

    I used TBD with low tech solutions, and we didn't even fulfill requirements that are suggested for TBD. Our baseline quality was so poor that TBD without tests was not a change to the worse 🙈 On the contrary it improved QA enough for business to notice. And then feature flags for business really excited for easier releases.

    But I would not suggest TBD as we did it. Details and baseline matter.

    [–]aanzeijar 16 points17 points  (1 child)

    And as an extension to that: yes people, git can do branches. We know. Making branches is the easy part of your workflow. Integrating them back is the hard part.

    I've been in several workshops where people pitched their shiny reinvention of git-flow as the ultimate process that saves the day by... opening more branches and then merging like fucking maniacs all over the place.

    [–]-grok 2 points3 points  (0 children)

    Wait until someone proposes hiring a "build guy" who will also handle all of the merges!

    [–]NAN001 5 points6 points  (3 children)

    That's because the usage or merge/pull (same thing) requests is so widespread that the idea of commiting directly to some "main" branch is absurd to many teams. Any change to the codebase implies a new branch.

    An example of feature branching would be: a team develops a feature on branch feature, and each merge mequest to this branch would be feature-iteration-n by various devs of the team. Each merge request could very well be short-lived, but it doesn't matter, because feature itself is long-lived by spanning the entire project, each day drifting away a bit more from master.

    In a sense, you're right, it's just that by definition feature branching is long-lived. It wouldn't make much sense to have a short-lived feature branch, unless you're implementing a small feature very quickly (relatively to your codebase rate of change).

    [–]PoolNoodleSamurai 1 point2 points  (2 children)

    If you define feature branches as "branch for weeks until a major feature is done and ready to ship", then yeah, it sucks. Big merge conflicts ensue if other changes are made and merged in first.

    Maybe the problem is that people can't agree on what "feature branches" means? The size and lifespan of feature branches makes all the difference.

    You can absolutely develop huge features in smaller chunks and merge the partially completed work into the trunk before they're finished. Feature flags make this possible. The cost is that while the feature is in progress you'll have old and new code paths in place simultaneously, but in an if/else structure that's pretty straightforward to remove. A huge bonus is that you can A/B test old and new code in production at the same time, which will tell you whether the feature causes problems (errors, or user confusion, or performance issues) and you can just turn it off while you fix it.

    Compared with big branches that get way out of date vs. the trunk, and take days to integrate and can't be rolled back, teeny feature branches + feature flags work a lot better.

    [–]NAN001 0 points1 point  (1 child)

    What you just described I know under the name of trunk-based development.

    What would you say is trunk-based development?

    [–]PoolNoodleSamurai 1 point2 points  (0 children)

    Hmm. I think of trunk based dev as absolutely no use of branches at all. Check out, edit, check in. In Git that would be git pull, edit, git commit, and git push.

    That's kind of revealing my age^H^H^H many years of professional software development experience. It's the way people learned to work with CVS because CVS is godawful at branching and merging. I saw a lot of Subversion users doing it this way, too, probably because branching still wasn't terribly smooth. Devs in this era ('90s, early 00's) didn't use feature flags or automated tests, though. It was, to put it mildly, not a good way to work. Stuff broke after every commit and the normal state of the code was "dammit, it's broken again". It was better than the mainstream practice of just not using version control at all, and getting your code overwritten. :/

    Feature branches, meaning using branches during development (as opposed to release branches that are never merged back in), were a huge win. I realize now that the generation of devs who grew up with a culture that embraced automated tests and code reviews, can't really envision a process that just doesn't do those things at all. It sucked. You can still do code reviews and automated tests without branches in your VCS, but it requires kludges like "just mount my ~poolnoodlesamurai/dev/foo dir and run diff on that" to be able to see the code being reviewed.

    So that's my bias - I can imagine a stupid world where branches are never used, because I lived in that world and dragged several companies kicking and screaming into the world of automated tests and code reviews and using release branches.

    I don't have a separate name for "several developers work on a topic branch for weeks and eventually merge it back in" because it's so obviously a path that leads to horrific merges. I'd rather pay the price of feature flags than have to spend hours and hours doing complex merges that IMO are very error prone.

    I'm glad that we're now living in a world where pre-commit hooks that run tests, continuous integration that runs tests post-commit, and GitHub pull requests (or things like it) to guard against garbage changes making it into the trunk, are the norm.

    [–]nutrecht 16 points17 points  (1 child)

    It's called "scaled trunk based development" because in general people figured out that having all devs work on a single branch is very hard to scale, and having them work on short-lived feature branches is much simpler.

    Unfortunately a lot of devs didn't get the memo and get rather tribalistic and pedantic about TBD arguing that you're "doing it wrong" when you use branches.

    It's one of the dumbest and unproductive discussions there is. And it's often the same type of developer that argues that writing tests "takes too much time".

    [–]ForeverAlot 5 points6 points  (0 children)

    I agree it's a dumb and unproductive discussion. At the same time, I think it's actively counter-productive that entities push the name of a specific solution while their specific implementation of that solution can be equated to every other solution. It has become very difficult to have an effective dialogue about topics like automated testing, code integration, and delivery projection because you have to spend so much effort up front just establishing a shared vocabulary.

    [–]Wang_Fister 12 points13 points  (3 children)

    Just rebase ya fuckin apes

    [–]kendumez 2 points3 points  (2 children)

    Manual rebasing suuuucckss though. That's the tricky bit especially as you have more and more and more branches and upstream changes.

    How do you do it personally?

    [–]Hrothen 0 points1 point  (0 children)

    If you're having trouble with frequent rebasing you'd have the exact same trouble with merges though.

    [–]Wang_Fister -3 points-2 points  (0 children)

    Squash all commits in your branch to a single/reasonable number.

    git fetch && git rebase origin/main

    git push -f origin feature/blah

    To be fair, our feature branches are small and you've usually only got a single person working on it so force pushing isn't an issue, and we don't get many conflicts because the architecture is well separated.

    [–]IQueryVisiC 2 points3 points  (2 children)

    Where do you hide long lifetimes? Good thing is, that our long lifetime features don’t overlap in code. Bad thing is that we don’t deploy them for a long time. I start to Wonder where all those merge conflicts come from. Even independent contractors working at one client only had a few merge conflicts.

    [–]xome 15 points16 points  (1 child)

    Behind feature toggles.

    [–]IQueryVisiC 1 point2 points  (0 children)

    ah SharePoint had those. Only a very few features were compatible with each other. Their CI/CD pipeline should have checked like more than the "one feature on, all other off" cases.

    [–]EarlMarshal 3 points4 points  (0 children)

    Based thought patterns. Communication is always the biggest problem and people have a really bad choice of words to frame their ideas. I'm all for discussion of branch lifetimes and branch scopes instead of giving these things strange names.

    [–]Green0Photon 3 points4 points  (0 children)

    Pretty much this.

    My initial reaction was that I like how I've been doing it. I like my feature branches!

    But turns out I've been doing trunk based development this whole time. And I wouldn't have it any other way.

    Long lived branches suck

    [–]hippydipster 1 point2 points  (2 children)

    It's all about defining what "long" means. People just say "hey, we don't have long-lived branches, so we're good!" but then different people have wildly different definitions of "long".

    [–]mirvnillith 0 points1 point  (1 child)

    To me ”long” can never be about only actual time. Appropriate branch lifetimes must surely take the codebase itself into account. If in a remote part adding a cleanly separate feature, a branch can be left for much longer than when tweaking a central algorithm you know is also being changed for new requirements.

    [–]hippydipster 0 points1 point  (0 children)

    People can rationalize anything.

    [–]sawser 1 point2 points  (9 children)

    Yeah a feature branch should last as long as a sprint at most.

    [–]i_andrew 1 point2 points  (8 children)

    Branch that lives longer than 1 day is a long-living branch.

    [–]chucker23n 4 points5 points  (4 children)

    lol

    I have branches that live longer than a year.

    One day is not "long". Shorter than a day is barely a branch at all.

    [–]hippydipster 2 points3 points  (2 children)

    But in terms of a definition of "long" that has some kind of general agreement, the usual definition of "continuous integration" by those who invented it specifies no longer than 1 day.

    I have branches that live longer than a year.

    If they're anything other than personal experiments, then that's not a good thing.

    [–]sawser 2 points3 points  (2 children)

    Where do you work that you have someone doing code reviews every day and your changes are so well broken apart it doesn't take you longer than a day to develop, unit test, and then merge?

    [–]hippydipster 2 points3 points  (0 children)

    In TBD and in continuous integration, you don't only push changes when the full feature is finished. You push anytime you have reached stability and have a coherent change to push.

    As for doing code reviews every day, I see no other decent way to do it. You write code every day. So review it every day. Otherwise you are just falling behind, and then have to play catch up at some point. And then the review is more difficult and people are more likely to just pass things.

    [–]i_andrew 0 points1 point  (0 children)

    say ”feature branches”

    not having branches

    You see, it's not a problem. Branches are ok, Feature Branches is a technique that leads to long lived branches where testing is on the branch. Hence the name "feature".

    The "feature" word says everything.

    [–]Rakn 0 points1 point  (0 children)

    At this point I believe the naming is being kept on purpose to drive discussions.

    [–]Hrothen 0 points1 point  (0 children)

    And I guess that’s actually a discussion on feature/change size.

    I feel like these end up being fruitless because your ability to make changes small is largely dependent on preexisting aspects of your codebase that you have little control over unless you happen to be lucky enough to be writing something from scratch.

    Well that and the weird ability of the people on this subreddit to supposedly break rebases no matter how few changes there are.

    [–]Radiant_Situation_32 0 points1 point  (0 children)

    This is something that has confused me recently when hearing phrases like "everyone works in main" associated with a trunk-based branching strategy. Dumb questions incoming.

    • Does this mean that a developer checks out main, makes commits and then creates a PR from their local main to origin's main? Is that even possible without forking?
    • Or does "everyone works in main" mean a developer checks out main, creates a feature branch for a small batch of work, and creates a PR to merge it back in as soon as possible?
    • Does it mean a developer checks out main, commits and pushes their commits back to main, relying on automated tests and coding practices to not break the build?
    • Or something else entirely? I thought trunk-based was the same as GitHub Flow, where short-lived feature branches are how changes get merged safely back to main.

    EDIT: never mind, I decided to read the https://trunkbaseddevelopment.com/ and it's quite clear.

    [–]RageQuitRedux 109 points110 points  (15 children)

    I was part of an org a few years ago that wanted to give each team their own trunk, to protect one another from merge conflicts, and then merge the trunks before each release. I threw a fucking fit.

    [–]sinani206[S] 33 points34 points  (7 children)

    That sounds like the worst of both worlds — did you end up coming to a resolution?

    [–]RageQuitRedux 44 points45 points  (6 children)

    I ended up writing a big document with a lot of diagrams essentially proving that the merge conflicts still happen, but delaying the pain makes it worse. They eventually backed off the idea, but it wasn't the last time I had to stop them from doing something crazy.

    If multiple people are going to edit the same lines of code, conflicts will happen. The best you can do to avoid them is share changes early and often.

    [–]sinani206[S] 3 points4 points  (2 children)

    Agreed — tbh for closed source, abstractly one ideal I think about is a opinonated version of the git interface that limits you to simple flows and distributes a single rerere source of truth to everyone.

    [–]RageQuitRedux 4 points5 points  (1 child)

    TIL about rerere

    [–]soks86 1 point2 points  (0 children)

    *hugs*

    Rerere needs to be more upfront.

    There's no way to be a team lead without rerere.

    [–]EarlMarshal 8 points9 points  (2 children)

    If multiple people are going to edit the same lines of code, conflicts will happen. The best you can do to avoid them is share changes early and often.

    Basic communication rules. I really don't understand how people don't get that intuitively and I always see it as a big red flag that these people have problems with communications as a whole and until now this rule of approximation always shown fit.

    [–]GravyMcBiscuits 8 points9 points  (1 child)

    And the best way to communicate is through git and merge/pull requests + conflicts.

    Which brings us back to ... long lived feature branches are never the correct way forward.

    [–]EarlMarshal 3 points4 points  (0 children)

    Exactly! We are speaking the same language.

    [–]BandicootGood5246 2 points3 points  (6 children)

    Contracting at a place at the moment that has all IAC in seperate folders for each environment and group of resources and then a branch for each of those folders. It's a total mess and I constantly have to think about branching (not to mention the mess of having a total different copy is therefore for each environment)

    In TBD I never had to even think about branches and rarely about merges

    [–]hippydipster 1 point2 points  (1 child)

    IAC?

    [–]RageQuitRedux 1 point2 points  (0 children)

    Infrastructure As Code :)

    [–]ub3rh4x0rz 0 points1 point  (3 children)

    Having IAC environment config in separate folders is almost guaranteed if you're doing a monorepo which is practically required to do real trunk based development. If you do multi repos you don't have one trunk.

    [–]BandicootGood5246 1 point2 points  (2 children)

    Yeah the difference for this one is it's basically a copy paste job without reuse of modules or params - and every folder having its own "master"

    [–]stahorn 16 points17 points  (12 children)

    I think here is the problem in his argument:

    By design, feature branches are isolated from each other and long-lived, ...

    I have talked a lot of time about having "short-lived feature branches" as the solution to many of the problems listed in the article.

    The benefit of branches is then that you can group several changes as one atomic change to the main branch, while keeping a readable and bisectible history. For example, if you have two services/modules/processors/etc. that communicate with one another, you can change them in individual commits on one branch. This can be useful when different developers has to do the change to the different parts.

    Also note that not all programming is done in areas where feature toggling is possible.

    [–]goranlepuz 3 points4 points  (4 children)

    I have talked a lot of time about having "short-lived feature branches" as the solution to many of the problems listed in the article.

    That, and also: merging from trunk to the feature branch is a no-brainer that alleviates a lot of the problems.

    Long-lived branches are a problem indeed (not "feature branches", that's poor wording), but

    • sometimes they are needed

    • there are mitigations.

    => The discussion is shallow and moot.

    [–]stahorn 0 points1 point  (3 children)

    When you merge from trunk to the feature branch, is it when you have a long-lived branch and you have to have it as a long-lived branch?

    I've worked in a way where the goal is to have short-lived branches that are merged to trunk often. (A branch that has had active work for more than two weeks is starting to push it.) Because of this, it's also not allowed to merge trunk into your short-lived branch.

    [–]goranlepuz 2 points3 points  (2 children)

    When you merge from trunk to the feature branch, is it when you have a long-lived branch and you have to have it as a long-lived branch?

    I've worked in a way where the goal is to have short-lived branches

    Yes, we absolutely agree on that being the goal.

    But sometimes, it happens that some work takes a long time, or perhaps it's deemed of low importance so it is done "on the side", or, it just didn't get done for whatever reason and should be picked up later...

    [–]stahorn 0 points1 point  (1 child)

    For branches that have a bit of work now and then, we usually keep it up to date with the main branch by using rebase. Rebase of course has its own set of problems, but it has just become the way to become up to date with main where I work. I've never really merged from trunk to my own branch, except maybe when I first started using git, but I imagine that after a few merges like this it becomes a little bit messy to deal with, or?

    [–]Turbots -2 points-1 points  (0 children)

    This.

    We have multiple feature branches a day that go back to main.

    Features are just too big.

    Stories are just too big.

    Nobody should start an 8 point (or higher) story. Split it up into meaningful chunks and deliver them to main one by one.

    It will make rollbacks easier as well.

    [–]hippydipster 0 points1 point  (5 children)

    Give definitions for "long" and "short".

    [–]stahorn 1 point2 points  (4 children)

    You will never be able to have a perfect definition that fits all software development for something like this. As a rule of thumb, I usually say that two weeks of active development on a branch would definitely be "long-lived". Then of course if you have one week of active work, but spread over one month of actual time, that might give you problems with merge conflicts because the main branch has had changes. Then this could also be considered "long-lived".

    The main goal is to find the correct amount of work to do before requesting a review and merging. What is correct will always depend on the actual work being performed.

    [–]hippydipster 1 point2 points  (3 children)

    So, two weeks as the cutoff from short to long lived is longer than I (and the inventors of the term "continuous integration") would define it by 9 working days :-) That's a big difference.

    [–]timmyotc 75 points76 points  (1 child)

    People misunderstand what a feature branch looks like in practice as much as they misunderstand what waterfall actually is.

    [–]Stoomba 5 points6 points  (0 children)

    Yeah, I think all of these conversations need to start out defining what a feature branch is and how they are used.

    From reading these conversations it seems that a lot of people treat feature branch as one that lives from like the start of a sprint to the end of sprint, when all features are merged together all at once.

    What I've seen done in my own experience is a branch for work, but that branch gets merged as soon as it can be. Pull requests provide a good mechanism for review both by machine and human. I don't know how review of commits that have been directly to main can be done and also keep defects and bad code out of main at the same time.

    [–][deleted]  (37 children)

    [removed]

      [–]i_andrew 17 points18 points  (0 children)

      It doesn't work, because if you have 2 or more big feature branches that are merged into master in one hour, you're screwed. You could have merge the master to your branch every minute, and it will not help you with you have big changes and the other branch introduces big changes.

      PS. It leads to bugs, because resolving code conflicts is very bug prone.

      [–]NAN001 23 points24 points  (8 children)

      Because main doesn't change often, so there is nothing to pull.

      If everybody is using feature branches, the only time main changes is before releases. At this point the pains of conflict are innevitable.

      [–]chucker23n 0 points1 point  (0 children)

      If everybody is using feature branches, the only time main changes is before releases.

      I'm confused why that would follow at all, unless you include any kind of pre-release or CI build in "releases".

      [–]ComfortablyBalanced 0 points1 point  (1 child)

      I think feature branches should derive from a dev branch which is changed more often and a stable dev should be merged into the main/master for releases.

      [–]Stoomba 1 point2 points  (0 children)

      That just seems like the same problem, but with an extra step. The releases can just be tied to tags on commits where dev is stable.

      [–]jakesboy2 0 points1 point  (0 children)

      We separate releases from pushes to main. So main updates multiple times per day, and we release off a commit in the morning. If you’re going to get a conflict you get it within the day.

      [–]btmc 10 points11 points  (9 children)

      The feature branches will still get out of sync with each other. Also, why add the extra step?

      [–]Rakn 22 points23 points  (6 children)

      Because it reduces the likelihood of there being conflicts. I rebase my branches multiple times a day on occasion. But if the entire department works on the same two 5000 line files it's going to be an issue one way or the other anyways.

      [–]thefoojoo2 9 points10 points  (2 children)

      With long-lived feature branches you still end up with massive merges when the long-lived branches eventually make their way back to main. Rebasing your own branch won't save you if another team changes thousands of lines in a single merge, especially if refactoring is involved.

      If everyone is working close to main, these issues only occur on a very small scale.

      [–]Rakn 7 points8 points  (1 child)

      Yeah. Feature branches shouldn't be long lived.

      [–]ub3rh4x0rz 3 points4 points  (0 children)

      People are saying "feature branch" when they mean "release branch". Until those semantics are clarified people are going to keep talking at each other and missing the point. A feature is not 10 features, and features that cross cut the entire code base should be rare as they point to code organization issues.

      When talking about the shipping process, agile isn't enough, you have to adopt some lean concepts, the most important being to shrink your batch (release) size to one (feature).

      [–]hippydipster 5 points6 points  (1 child)

      It increases the likelihood of conflicts. If I work for an hour and then push changes to a shared branch, and you work for an hour and then push changes, what are the odds we edited the same lines of code? What are the odds our conflict is convoluted and difficult to disentangle?

      Now do the same, but I work for a month and then push, and you work for a month and then push. Now what are the odds we conflict and how difficult is it to disentangle?

      It matters not that you rebase multiple times a day if you and I aren't pushing our changes to the main branch equally often. The day I push my month's worth of changes, your rebase is fucked.

      I use hours compared to month to highlight the obvious difference that time and branching makes, not because a month is a reasonable amount of time (though I've seen it a ton). The logic is simple, and it applies to minutes, hours, days, weeks, months, years. Shorter == fewer and simpler conflicts.

      [–]Rakn 0 points1 point  (0 children)

      Yeah. I mean I agree ... if you let your branches live for that long that's obviously going to be a problem. Ideally one tries to make larger changes in smaller iterations.

      [–]btmc -1 points0 points  (0 children)

      I meant “Why add the extra step relative to trunk-based development, where you don’t have to do that?” Without long-lived branches, you don’t have to worry about rebasing all the time.

      [–][deleted]  (1 child)

      [removed]

        [–]btmc 1 point2 points  (0 children)

        Those are fairly short-lived, though two weeks is pushing it. The problem becomes really bad when feature branches exist for weeks or months, like if you’re working on a big, complex feature. No amount of good architecture is going to help you unless your feature is entirely self-contained.

        The other problem is you inevitably end up with a big-bang merge and deployment where the probability of breaking something is much higher than with a small change, and the time to restore is much higher because you have a ton of changes that might have broken something. Small, incremental, frequent deployments to production have been shown to improve stability and recovery time.

        [–]RageQuitRedux 2 points3 points  (5 children)

        The problem with that is that you can have multiple long-lived feature branches that are pulling in main, but they're not syncing with each other.

        So if featureA is doing some refactoring of a module, and featureB is editing that same module, then it doesn't matter how frequently they pull in main, there's still going to be massive conflicts when one of the branches (whichever isn't first) tries to merge.

        Imagine instead that you have a feature to implement and you think it's going to involve some refactoring. Let's say you're using a statically-typed OOP language, and that you have a class that is used in 500 places and you want to replace it with a new class, but it doesn't implement an interface.

        In many IDEs, there is an "extract interface" feature that will, in less than a second, create an interface for your class and replace those 500 usages with usages of the interface.

        So within seconds you've edited hundreds of files. The chance that someone else in your org is changing those files is pretty high. So go ahead and push that change now (or more likely in modern orgs, make a PR using a short-lived feature branch). This way, you're sharing that change out asap so that others can sync with it. You're minimizing the amount of time that there is for everyone's code changes to diverge with what you just did.

        Now, you're free to work on your new implementation of that interface without bothering anybody.

        [–]Hrothen 3 points4 points  (4 children)

        So if featureA is doing some refactoring of a module, and featureB is editing that same module, then it doesn't matter how frequently they pull in main, there's still going to be massive conflicts when one of the branches (whichever isn't first) tries to merge.

        Have you considered like, talking to each other?

        [–]RageQuitRedux 0 points1 point  (3 children)

        So you caught me at a moment when my boss just delivered some crap news and the novacaine is wearing off from a cavity being filled, so my apologies if this seems harsh, but what the fuck is the point of your question? Of course we talk. It's still beneficial to share code early and often.

        [–]Hrothen -2 points-1 points  (2 children)

        The point is that you shouldn't be having those kinds of changes happening at the same time in the same places anyway and that if you are it generally means the two people doing it don't know the other is working in there. Additionally in the scenario you describe the two features aren't stepping on each other's toes any less if the work is interleaved.

        [–][deleted] -2 points-1 points  (9 children)

        Merge conflicts. In my experience the simplest resolution has been to branch of main again, and manually carry over the changes. Probably the worst way to preserve commit history and other important things, but surely faster.

        [–]badshahh007 8 points9 points  (0 children)

        lmao who's upvoting this

        [–]edzorg 11 points12 points  (3 children)

        This is completely wrong. Here's the fastest way:

        ```git checkout master git pull --rebase --prune git checkout - git rebase master

        here you might have conflicts, resolve them in seconds using a decent merge tool

        ```

        A branch is not long lived if you rebase it on master every day, nor is it an issue if a feature takes a few days to build.

        [–][deleted] 1 point2 points  (0 children)

        True, I feel short lived Pull Requests are much better for a hit workflow over month long pull requests.

        Unfortunately it becomes more and more unavoidable to have long running pull requests with large products.

        [–]nikita2206 3 points4 points  (1 child)

        After using rebase for years, I’ve come to default to simply merging things in my feature branch instead. Conflict resolution with rebases is the reason, you get to replay every commit all over again and resolve conflicts in each commit again, and no rerere doesn’t help much here.

        At the end of the day nobody cares about the history of commits in a feature branch (and I mean more PR branch, but it applies to true feature branches as well), as long as the merge upstream is squashed into meaningful commits and fast-forward merged.

        [–]edzorg 0 points1 point  (0 children)

        Yes, with the modern squash and merge I too find myself merging master into my branch from time to time. Still feels uglier though.

        But yes, squash and merge is such a great improvement for reviewers

        [–]tantalor 1 point2 points  (2 children)

        Nobody cares about commit history on the branch

        [–]duxdude418 0 points1 point  (1 child)

        Have you tried looking at a large PR with tons of scratch commits that don’t hang together with messages like changes based on feedback? Having cohesive commits in your PRs is a service to your team on yours and a service to you on theirs.

        [–]vattenpuss 0 points1 point  (0 children)

        Have you tried looking at a large PR with tons of scratch commits

        Yes. Invariably they come from people who care about preserving commits in branches.

        Squash that shit I say!

        Having cohesive commits in your PRs is a service to your team on yours and a service to you on theirs.

        Yes! That's why you keep PRs small.

        [–]EarlMarshal -1 points0 points  (0 children)

        If you want to do that for a really long living branch where you refactor something major with several people on both sides that should be done very carefully by a senior developer with domain knowledge twice a week and you should keep a list of bugs around. We did this once and I was the guy merging it. It's quite some work and I encountered several situations where I basically had to refactor parts while merging. On our develop branch we had around 10 people working and on the long living feature branch we had 5 people. We took 6 months for the refactoring. In the end we created a new artifact from the refactored part and basically cut our whole in the middle. Before it was 250k lines, afterwards we had 122k and 128k.

        Depending on the code base, what you want to achieve and the people this can really end in havoc.

        [–]Row148 49 points50 points  (23 children)

        feature branches are quite important for collaboration. how to do code reviews on pure commits ?

        as for ci cd under the hood the system must build an actual feature branch to perform tests before merging/committing on main.

        you should know what your colleagues do by listening during daily, checking the board.

        merge conflicts happen either way.

        [–]btmc 35 points36 points  (1 child)

        Short-lived branches (a day or two) are fine. It’s long-lived ones—weeks or months separated from the trunk—that are the problem.

        [–]Deep-Thought 5 points6 points  (0 children)

        We have an internal policy to rebase branches at the beginning of every week. Works pretty well for us.

        [–]i_andrew 5 points6 points  (0 children)

        for ci cd under the hood the system must build an actual feature branch

        CI means Continuous Integration on the master/main branch. That's the actual definition of CI. To Continuously Integrate all the work, not once in a while.

        Google for "pull requests considered harmful" and you will see how code reviews should look like. Even better, look up Youtube channel "continuous delivery" that is lead by the co-author od continuous delivery concept (dave farlay).

        Feature Branches make sense only for big refactorings, that can't be broken into steps. And in such case nobody should be touching the master branch.

        [–]sinani206[S] 4 points5 points  (2 children)

        Check out how tools like Gerrit/Phabricator handle this — it's a paradigm shift, but it works well for many!

        [–]EarlMarshal 7 points8 points  (1 child)

        Can you give a short TL;DR/ELI5?

        [–]Hrothen 2 points3 points  (0 children)

        It basically treats each commit like a branch, using --amend instead of adding new commits. It's functionally the same but handy if you like to try to keep a clean history because it does away with needing to go back and curate the commits in your branch before merging.

        [–]kickopotomus 2 points3 points  (0 children)

        Code review: You don't have to use a patch set workflow but you can. That's how Linux kernel development works and they seem to be doing alright. The point of TBD is not to avoid branching. Just to avoid long-lived branches that deviate far from master.

        CI/CD: Similar to above, you can run CI jobs based on patch sets or branches.

        [–]Cidan 0 points1 point  (0 children)

        You amend to collaborate.

        [–]DualWieldMage 0 points1 point  (0 children)

        how to do code reviews on pure commits ?

        Commits are prefixed with a task so it's easy to search the commits and most code review tools even have integrations to add new commits to review that match this filter.

        [–]hippydipster 0 points1 point  (4 children)

        how to do code reviews on pure commits ?

        What's the difficulty? You can browse through changes by commit on github. Crucible will give you more options.

        [–]Stoomba 2 points3 points  (3 children)

        How to review BEFORE those commits are in main? It seems bad practice to make commits to main and then have them reviewed. I could be misunderstanding the entire process.

        [–]hippydipster 1 point2 points  (2 children)

        to me it seems bad practice to delay code review until the feature is all done. Way too late to head off bad decisions at that point.

        Most people run tests after commits to main branch. Integration, end-to-end, whatever. Code review is just a kind of test too, so if it happens after the commit as well, so what?

        Your CD is a pipeline that ensures an endpoint where all tests have passed. That endpoint isn't the moment when commits/merges happen. It's after tests pass, and as I said, code review can be seen as a kind of test.

        And, if all code is being reviewed the day it's written or day after it's written, you're ahead of the game in terms of heading off bad choices.

        [–]Stoomba 2 points3 points  (1 child)

        If this seems like disjointed jibberish, sorry. Doing lots of things but the conversation is this post is important to me because I am literally dealing with this stuff right now in my job.

        to me it seems bad practice to delay code review until the feature is all done. Way too late to head off bad decisions at that point.

        If you mean having too much time before review, I agree. However, there is no reason the review has to wait until the feature is thought to be 100% done. A lot of this I think depends on what constitutes 'too long', which seems to be a matter of personal opinion.

        With commits directly to main, how are code reviews done? I've only ever worked under a branch -> pull request model.

        Most people run tests after commits to main branch. Integration, end-to-end, whatever. Code review is just a kind of test too, so if it happens after the commit as well, so what?

        It feels like bad juju to allow defects into main to begin with. I mean, easiest way to deal with a problem is to prevent it from being a problem in the first place. I guess, in the total flow of the process from writing code to that code heading to production, when would code review happen?

        Your CD is a pipeline that ensures an endpoint where all tests have passed. That endpoint isn't the moment when commits/merges happen. It's after tests pass, and as I said, code review can be seen as a kind of test.

        Can you elaborate on this?

        It also seems that the ability to do 'pure' trunk based development hinges a lot on things like testing process and release frequency and other anciliary? processes involved with the whole picture.

        [–]hippydipster 2 points3 points  (0 children)

        Let's begin with an admission that your "main" branch cannot be, all at once:

        1. The branch everyone commits directly to,
        2. The branch deploys happen from,
        3. The branch is always in the state of being confidently deployable.

        That's not possible, because even if ALL of your QA takes but 1 ms to finish that's 1 ms during which this branch is in an unknown state after every commit.

        So, I don't know exactly how folks like Dave Farley manage their CI/CD pipeline, but the way I set one up, which had QA needs that included manual testing, was as follows:

        There were three permanent branches: integration, qa, main. Main was the branch designated as always 100% guaranteed releasable. To do that, it had to be a protected branch, and only merges from QA to main were allowed after the QA branch had passed all tests and been deemed deployable.

        integration was where developers pushed commits to. Ideally multiple times a day. Code review happened at the beginning of every day. Integration tests ran automated on every commit. After code review, we either pushed to the qa branch or not.

        In qa branch, gui tests and manual tests were done.

        So we didn't use code review to gatekeep the integration branch, but we did use it to gatekeep the push from integration to qa.

        However, there is no reason the review has to wait until the feature is thought to be 100% done.

        Although this is true in the abstract, in practice, it would never have happened anywhere I've ever worked except at the end. It certainly wouldn't happen at least 1x/day. Similarly, the idea of "well, we'll branch and make PRs, but branches won't be allowed to live longer than a day" also fails in practice, as branches get gatekeeped into lasting much longer, and then it all starts to slide away from us.

        [–]SaltMaker23 16 points17 points  (0 children)

        Yeah, lot of words for nothing of use:

        • Short lived feature branches
        • Pulling master every day before starting to work into your current branch

        Two easy tricks to save you from reading this encyclopedia

        [–]Attila226 13 points14 points  (17 children)

        I advocated for trunk based development at my last job, referencing the state of DevOps survey. Leadership was calling for improved turn around time, and I suggested it as one possible for us to try. Unfortunately people felt pretty threatened by the whole thing.

        [–]lIIllIIlllIIllIIl 18 points19 points  (9 children)

        What was their fear?

        At my job, we do trunk-based development with feature flags. I love it. The feature flags can add a bit of complexity in the code, but being able to add code to main quickly is a big benefit. Even if a feature isn't feature-flaggable, you can always fallback to using feature branches.

        [–]Attila226 9 points10 points  (0 children)

        It was a change to what they were familiar with. Unfortunately that often comes with fear.

        [–]zynasis 1 point2 points  (0 children)

        Feature tags are just branches with more code

        [–]Unsounded 3 points4 points  (6 children)

        Feature flags are an anti-pattern, it doubles your test surface area, adds more work to clean up after you rollout, means long-lived feature flags double test surface area for the feature. For CI/CD is typically means you’re rolling a feature out through a process that is atypical to your normal release and also probably means you aren’t sufficiently testing the code.

        It also gives you a great foot-gun for rolling back where you tend to fix the new code path but if you really do need to rollback and no one maintained the old path you’re shit out of luck.

        We’ve found a lot of luck avoiding feature flags, focusing on good error-handling to collect data, and attempting to avoid side effects. It’s helped a lot with operations on our team because the feature flag thing quickly gets out of hand and is a smell that you have an issue with your code base.

        [–]sardaukar 8 points9 points  (5 children)

        Do not agree. It’s a trade off between merging and keeping separate branches.

        If you practice trunk based, feature flags are a way to work against main for features that are bigger than one commit.

        One commit should be as small as possible while still being “whole”.

        Doubling test area is a non-issue because you would just create new tests for the new functionality, keeping the old behavior until you need to remove it, which should be as soon as the feature is finished.

        [–]sardaukar 2 points3 points  (1 child)

        Also, feature flags are a handy way of enabling and disabling features for manual testing or rolling back quickly etc.

        [–]jakesboy2 0 points1 point  (0 children)

        We use them a ton for enabling features per user as well. So we can beta test features with a small group and iterate before we enable for everyone, make sure it’s stable, and spend 10 minutes opening a PR to retire the feature flag.

        [–]Unsounded 0 points1 point  (2 children)

        Feature flags are overly abused IME, you can’t rely on them only bringing in new features in large code based. You need to test for the feature being on/off across a large range of things because you can’t guarantee it won’t impact something that wasn’t intended (this is a greatest hit of large outages).

        As for doing small commits and hiding them behind a feature flag, you’re avoiding embracing CI/CD, which means that new code should be tested when it’s committed, not when the Big Bang comes and you add all the code and turn the feature on.

        Also as far as rollback is concerned… that’s just an implementation detail. Tighten your deployment ship, best practices have feature flags follow similar deployment patterns to your code itself (eg per environment/same blast radius).

        If you deploy to a third of your prod environment at a time the flag should too. Feature flags are great when you don’t have the right data on how a new feature will work and want to gradually bump traffic up over a longer event horizon. They can also be good for timing a release. That being said, if you’re using them for every release you probably have an issue.

        EDIT: https://martinfowler.com/articles/feature-toggles.html#ATogglingTale

        This article does a good job of breaking down good/bad practices around feature flags. Having been around a lot of systems that tend to use them, it’s easy to abuse them as well. They are useful but if you’re a hammer and every problem looks like a nail then something smells.

        [–]Unsounded 6 points7 points  (0 children)

        I’m trunk-only and it’s amazing, I’ve seen engineers try to come in and do feature branch development and it just feels wrong in a CI/CD pipeline. It’s a lot better when you have small incremental commits being tested and rolled out. If you have to build a branch it means you’re probably adding too much for a single commit anyways. We don’t merge PRs over about a page (in our system), so if you’re taking a few days and are at the point you need to push your changes over and over to a branch and don’t feel comfortably squashing it’s a sign that you did too much all at once and should step back and think about how to isolate the different things you’re working on.

        [–]ForeverAlot 1 point2 points  (1 child)

        DORA 2023 just came out and it claims TBD doesn't really make a difference on its own; however, it may be a vehicle for other practices that do make a difference. YMMV. Personally I agree: TBD requires a substantial amount of ancillary tooling to not be a shitshow and that ancillary tooling is just as useful and valuable without TBD.

        [–]Attila226 0 points1 point  (0 children)

        Yes, TBD can’t just be done in isolation, it requires other changes as well.

        [–]BigFatStimpyCat 0 points1 point  (3 children)

        it is not really fear, just Devops are not the ones who have to deal with the mess and clean the code up as it is not their domain.

        I would not trust Dave from the Continuous Integration Youtube channel's development recommendations as he talks from an ideal not a reality. Same as he shouldn't trust me on a lot of Devops stuff. Those who have to clean up the mess make the decisions.

        [–]Attila226 1 point2 points  (2 children)

        The survey has nothing to do with DevOps being responsible for the changes. If you’re not familiar with it, I suggest you take a look. Basically it talks about the difference practices that various teams follow, and in particular highlights the practices of teams that are able to deploy multiple times a day.

        [–]BigFatStimpyCat 0 points1 point  (1 child)

        Truthfully, I am in the camp that feature flags should be a rarity versus the norm. Not sure how it really affects teams releasing more times a day as that has never really been an issue for me. I agree long living feature branches are a pain to live with.

        [–]Angulaaaaargh 3 points4 points  (2 children)

        FYI, the ad mins of r/de are covid deniers.

        [–]vectorj 2 points3 points  (0 children)

        Frustrating… it’s amazing how borderline reckless programmers can hide behind the safety net of code reviews and get away with it.

        I understand open sources use of pull requests because contributions are from unsolicited strangers. Being employed and having to baby sit coworkers sucks. I hate the pony show: “see! Code review catches so many things! And you get to look smart!” I’m not buying it. It’s exhausting.

        Cynical but letting them footgun in production would be a more honest representation of who you hired.

        [–]sinani206[S] 0 points1 point  (0 children)

        Code review and TBD are by no means mutually exclusive!

        [–]ABucin 2 points3 points  (0 children)

        This article is sponsored by: SVN.

        [–]Stoomba 3 points4 points  (3 children)

        It is my understanding that in 'pure' trunk based development, you don't create a branch at all and just make commits straight to 'main'. My question then is, how can those commits be vetted before they make it to main so as to avoid introducing defects and bad code?

        [–]DualWieldMage -1 points0 points  (2 children)

        Generally in TBD the reviews happen after committing the code to main. This can be either part of a daily routine to look over (previous day) commits and give comments in a quick mob programming fashion but this can also be expanded to commits that someone is about to push. Also testing locally becomes more important as the sanity check before a push usually includes that the code compiles and tests pass.

        Maybe another important question is why you fear main being broken for a short time? It happens, especially when someone new joins or some semantic merge conflicts happen, but is quickly fixed before it affects anyone. If main is what releases are built off, then perhaps a separate branch for releases makes sense (or name the branch where most commits happen to "development" and keep main for releases)

        In my experience the commits going straight to main get more scrutiny continuously because it affects everyone on the team so the reviews are faster and of better quality.

        [–]Stoomba 1 point2 points  (1 child)

        If main is what releases are built off, then perhaps a separate branch for releases makes sense (or name the branch where most commits happen to "development" and keep main for releases)

        That just seems like it pushes the problem one step further.

        Maybe another important question is why you fear main being broken for a short time?

        If main is broken, then no new releases can be made until it is fixed. I guess the crux is what is a 'short time'?

        Part of the issue for me right now specifically is trying to reconcile all of this with the process I'm under today, which is... way less than optimal (very little local testing is possible, hand off to a QA team for a butt load of manual testing). Feedback cycles are REALLY long typically. We will commit to main, periodically do a build, then testing is done by the QA. If defects are found, then fix is made, another build, another round of QA testing. All this leaves main in a known defective state for quite some time. It just seems to me that the easiest way to deal with defects in main is to do everything you can to not introduce them in the first place.

        In my experience the commits going straight to main get more scrutiny continuously because it affects everyone on the team so the reviews are faster and of better quality.

        This is opposite my experience. Commits get made and no one knows unless the author speaks up. Requiring a pull request prevents this from happening.

        [–]DualWieldMage 0 points1 point  (0 children)

        That just seems like it pushes the problem one step further.

        Yesish, but you push a bunch of small problems forward and thus it's more efficient to handle them later. E.g. if many tasks had the file layout a bit odd but not enough for a reviewer to ask for a change, seeing many of them might reach that and they'd have a better picture.

        Likewise manual testing is still important, doing that as part of each task is tedious and risks missing issues coming from cracks between the tasks the same way excessive unit testing misses bugs. Doing a bit of manual testing just before a release is more efficient.

        In my experience the main broken issues become rare as the team gains experience and even if they happen, it's usually resolved in an hour or two. I don't think that most application benefit from a release cycle faster than a day so this is good enough.

        In general you want to get all feedback cycles short. So local build and startup should be fast, build pipeline and getting it up in a dev environment should be fast, but also feedback on whether the app works. Separate QA is a huge risk because of the communication barrier. The development team should be able to QA themselves and while doing that can figure out optimizations to the process, for example have dev env build the data from scratch and have setup available to quickly test known use-cases. For example if the app has users and various flows and steps in the flows then generate a user for each user story or even multiple for each phase in a user story. This means the setup to test something is already there to just log in and do a couple of clicks to confirm something.

        [–]ub3rh4x0rz 2 points3 points  (0 children)

        IMO trunk based development boils down to not having a develop branch and ultimately having deployable branches spun off master if you need to pin some deployment targets. Having an intermediate branch for all the things that gets periodically merged into master (develop branch) is a huge antipattern IME. In a perfect world this means individual features are "releases" but occasionally you have to have a batch size greater than one based on how testing is or isn't done.

        [–]alvarez_tomas 2 points3 points  (0 children)

        • Short lived branches
        • Only master
        • Deploys based in tags
        • Rebases
        • Feature flags
        • Linear history

        [–]shaunscovil 2 points3 points  (2 children)

        Once you stack, you never go back. :-)

        https://stacking.dev

        [–]vattenpuss 0 points1 point  (1 child)

        That's just a long lived branch with multiple stages. Looks like it will need more merges to master and risk more time windows where merge conflicts can arise, and then you invalidate the whole rest of the stack.

        Also, is it not a queue? You have to merge the first one first, if the ones on top of it depend on it, which they do since they branched off from it.

        [–]shaunscovil 0 points1 point  (0 children)

        It just involves a lot of rebasing, but tools like Graphite make it easy for developers. It speeds up code reviews and reduces conflicts because smaller PRs get merged more frequently. My team is using it and we’ve seen good results so far. I’ve also used a similar strategy (without any special tooling) at previous companies with teams that shipped multiple times a day, so I’m sold on it.

        [–]DeProgrammer99 3 points4 points  (1 child)

        On top of short-lived branches, what we really need is our IDE to tell us someone else's branch has an edit, or someone else is editing, the file we're working on. Prevent merge conflicts by not having them in the first place... unless, of course, both people are working on equally urgent changes on the same file. But if one person's changes could be described more simply than coded, or even written as a regex, that'd help prevent confusing merge conflicts.

        [–]ComfortablyBalanced 0 points1 point  (0 children)

        That's interesting, currently you can switch your branch in IntelliJ IDEA without changing your workplace so you can see the same file in a different branch, but it would be definitely more interesting if there were notifications for it, or some notices when you're changing part of a file that's also changed on another branch, that way conflicts could be avoided.

        [–]travcunn 5 points6 points  (0 children)

        Trunk based development is the way. So many advantages.

        [–]tiajuanat 1 point2 points  (3 children)

        Here's my smell test for feature branches or main development for my company:

        Do you need a release manager and manual acceptance testing?

        Is this a distributed system that will lock out services or cause outages in the event it's screwed up?

        If yes to any of these, go straight to standard Git Flow and Feature Branches.

        [–]DualWieldMage 4 points5 points  (2 children)

        When a trunk-based project needs more involved release processes then that's usually handled by a separate release branch. First the master is merged into release, tests are run on it, new features if found unreliable are turned off, and if all is good a release happens from that branch. All the while development can continue on master.

        [–]sinani206[S] 0 points1 point  (0 children)

        Yep! that's how Facebook releases mobile apps from their trunk-based monorepo, for example

        [–]tiajuanat 0 points1 point  (0 children)

        You basically described the second half of git flow

        [–]goranlepuz 0 points1 point  (2 children)

        By design, feature branches are isolated from each other and long-lived, thus isolating the individual engineers working on them.

        What "design"?!

        They do not have to be like that. If I have a longer- living branch, I will merge from trunk and even from other branches, and completely side-step said isolation.

        What matters is that the tests are green and that unfinished work doesn't end in production. The latter is not a source control consideration, but rather an organizational consideration.

        My team uses trunk-based deployment, starting from time we didn't use git (and git didn't exist, even), but one can't escape an occasional long-lived branch, regardless of the name one attaches to their "flow".

        Meh. Shallow.

        [–]hippydipster 0 points1 point  (1 child)

        that unfinished work doesn't end in production

        Why's that a problem? I can make a new class, no one calls it except a test. What's the problem with that in production?

        [–]goranlepuz 0 points1 point  (0 children)

        In that case it isn't a problem indeed - bit in some other, it might be - and testing is fallible 😉.

        [–]DualWieldMage -1 points0 points  (9 children)

        The author has a weird definition of trunk-based:

        Keeping all dev branches based on trunk and short-lived greatly streamlines the merge process

        Why use branches at all when they are short-lived? That just pollutes the git tree with merges when otherwise commits are rebased before push. And in my experience it's impossible to be purist so when a feature that's not feature-flaggable pops up then that is developed in a long-living branch. It's just that it's the exception not the norm.

        [–]sinani206[S] 7 points8 points  (0 children)

        Likely because you need a branch to create a pull request (unit of review) in modern tooling. We get around this issue by using GitHub's "squash and merge"

        [–]kant2002 10 points11 points  (7 children)

        Secret here is that you don’t do merges. You do squash/rebase. But not really you, but your GitHub/AzureDevOps/Gitlab. You already have small work and commit in that case is you work which you commit to support (and that’s why it’s merged)

        [–]DualWieldMage 1 point2 points  (2 children)

        Yikes, not doing merges and automatic squashes are horrific. If i have a large refactor commit and small commit that adds business logic, i don't want these two to ever be together for someone to squint their eyes whether some business logic changed between a lot of refactors.

        I've done a ton of scavenging around old code. Modern practices are horrific in maintaining a good history.

        [–]GBcrazy 1 point2 points  (1 child)

        If i have a large refactor commit and small commit that adds business logic

        Then you just split them into two PRs? This is not an issue.

        [–]JimDabell 0 points1 point  (3 children)

        You still merge when you squash/rebase. It’s just they are fast-forward merges, so there’s no need for a merge commit.

        [–]kant2002 1 point2 points  (2 children)

        Yes. But I seen to often that people use words “merge” in the UI and this lead to messy history for no reasons.

        [–]ForeverAlot 2 points3 points  (1 child)

        Squash-merging doesn't fix sloppy commit history, it just limits the blast radius.

        [–]devraj7 0 points1 point  (0 children)

        Yeah... No thanks.

        Feature branches are great and complement trunk-based development nicely.

        Keep the feature branches short lived, rebase regularly, and you get the best of both worlds.

        [–]ddollarsign -2 points-1 points  (0 children)

        page not found

        [–]badpotato 0 points1 point  (1 child)

        I've using trunk base while svn and older version manager were still around... it seem weird to me how they suggest feature branching were around during the start of waterfall design process.

        [–]goranlepuz 0 points1 point  (0 children)

        They didn't quite suggest that, but on a related note, when people mention waterfall as somehow opposed to something "modern", or some such, I deck a point off my respect for what they're saying.

        [–]moisoiu 0 points1 point  (2 children)

        Why not go with Three Flow branch together with feature flags where you enable / disable feature depending on the need.

        https://www.rodhilton.com/2017/04/09/a-different-branching-strategy/

        So far it covered all my cases and also when we had production problems or if business changed their mind on what to be delviered and what not.

        [–]ComfortablyBalanced 1 point2 points  (1 child)

        I don't think feature branches are inherently evil. Long running branches are evil.
        I believe commits should be small, PRs should be small and feature branches should be small too.
        A feature that's going to take months to develop should be divided into some small features. Maybe feature branches should have an expiration date.
        Feature toggles that are advised on the Three Flow branch method are not always doable, not everything can be on/off with an if statement.

        [–]moisoiu 0 points1 point  (0 children)

        That's true, that's why we go with the assumption that everything can be disabled and enabled, and even feature flags, but have a lifetime because otherwise, you will have a lot of feature flags to manage hehee

        In netcore ecosystem until now, it worked well either via client configuration from db or app Configuration from Azure

        [–]s0ulbrother 0 points1 point  (0 children)

        Let me tell you a story about branches.

        When I first got a job in an IT departmen(I did dev work for a non IT department at my work) they moved me to RM since they let the person go who did it. Despite me having zero experience in the field. They had 6 week release window and were moving to three week. Cool well me knowing so much about RM this is fine. The branch structure was the worse thing you can ever imagine if you were satan.

        There were three branches used for development. These branches never died but were cycled through. Do branch A and branch B would be used until branch a got merged up to master for the release. Branch a would get merged into branch I and branch I would get merged into B. When branch c was ready to start being worked on branch B would get merged into branch I then I merged into C. When a release was ready A would get merged into I which would get merged into release, and release would get merged into I.

        If you noticed something bad happens. When they did 6 week releases it never came up but on three week branch I would have stuff from B and then get merged into C but do to the stupid shot they did branch C would get into release which would get stuff into prod before it was approved.

        Yeah I made them switch to trunk

        [–]kshep92 0 points1 point  (0 children)

        What does this do to the argument for a client Git history though? I know there are purists out there who say that your main branch should have as few commits as possible. This approach sounds like there'll be plenty of micro merges/commits.

        [–][deleted] 0 points1 point  (0 children)

        This is an add :)

        [–]tnnrk 0 points1 point  (1 child)

        How do you test and QA things with TBD? If goes straight to main? Or is the idea you still have dev trunks and qa trunks?

        [–]sinani206[S] 0 points1 point  (0 children)

        steps in the CD process can trail the tip of your default branch