Was this article written by ChatGPT? It's the same wishy-washy style. Ignore the article, the actual answer is always trunk-based development. Long lived feature branches will always come back to bite you.
Personally I love the feeling of pushing up a PR and realizing that the branch I thought was done actually has several weeks of merge conflict resolution to do. Nothing quite like it to make one feel alive.
I love the people standing outside my cube or saying "hey hinkley" in chat because even though I'm "good at merges" by developer standards I still have maybe a 90% success rate. And so I've either broken their shit, or they broke someone else's and they know I'm the closest we have to a git surgeon so they've come for a consult.
Yup ditto (and I'd assume most participants in this thread are also local VCS gurus) - and I've still had two occurrences in my professional life where I looked at the git conflict and just bailed - reading the original branch for inspiration but essentially just rewriting the change over a new and completely different system. Thankfully those were pretty early on and I think solid unit tests can really shine when it comes to trying to resolve merge conflicts. My biggest fear in rebasing/merging is that there's a function "doStuff(foo, bar, baz)" which still presents the same function signature but which had its effective code contract completely wrecked by some concurrent changes. Git is wonderful - but git can't do anything if it looks like everything in the files you're touching didn't change... but they secretly did change because there's a mess of interwoven logic between your file and another file.
Yeah if someone has as many merges in their branch as they have commits, I might allocate ten minutes to trying to cherry-pick their changes out, and if that doesn't work I tell them to paraphrase their code onto a new branch. Probably about the same number of times that you have.
You can have both. Some bigger features can take a while to complete and you can keep the pain to a minimum be rebasing your feature branch on the latest mainline branch often.
Rebasing regularly is a task that requires diligence, skill and good communication. I've built solo "out-there" feature branches that I've kept alive through careful rebasing for more than a year without issue - but once you're working on a team absolutely everybody must be onboard with the strategy for it to work... as soon as people go off on a garden path doing unnecessary refactoring[1] in a big long-lived feature branch you start into the world of pain - refactors (especially code movement within a file like function reordering) lead to all sorts of unnecessary chaos. If you're going to make a long lived feature branch you absolutely need to KISS[2] - the smaller your change set the better your chances of avoiding having a bad time.
1. IMO refactoring is one of the best things you can do for your codebase but it should NEVER happen in a branch that may be blocked from merging for other reasons - keep refactors in isolated branches if there's any danger of your merge being delayed for any reason other than an issue with the refactor.
2. Keep It Simple, Stupid - i.e. avoid any complexities not absolutely necessary for the feature.
Development, like construction, is horribly ineffective at accurate projections.
So if it's "your turn" to have the (singular) long lived feature branch, you will run over your deadline and into someone else's start date. There will be someone you're blocking who starts pressuring you to finish or for the org to make an exception and allow 2 feature branches.
And six months later, what was good for the goose will be good for the gander and then you have 2 feature branches part of the official process. Which of course means you'll occasionally have 3. After that it's like Texas Highways. They just keep getting more lanes and traffic gets worse.
It's not about long-lived branches. It's about defining a solvable problem and having the discipline to finish your work on that problem before merging.
> Branching strategies like Git Flow popularized this approach, and it's extremely common in open source software, where typically community contributors do not have mainline access, and so much create branches and make pull requests
No? I thought Git flow had feature branches, but those were not supposed to live long, just like in every case. Long-lived feature branches should get long-lived by necessity (someone working a long time on a feature that can't or shouldn't be cut down), not by choice. In open source, feature branches are long-lived because either they don't get reviewed or the contributor lost interest/does not have the time to finish it. They didn't choose to make those branches long-lived.
Maybe I just misunderstand what "long-lived" means in this context.
Oftentimes the argument is made that even work that can't be broken down should still be frequently integrated, and instead you use feature flags to control whether it's active in production.
I haven't had enough experience working that way to say whether it's better. But I will say this: the root cause of many of the nastiest regression defects I've had to deal with was surprising outcomes when merging a long-lived feature branch into code that had had a few weeks of time to accumulate behavioral changes since the feature branch's creation.
I have found that I need to be specific when I talk to developers about "long lived" branches. In the past I have questioned teams about why they are developing in long-lived branches and they defensively claim they aren't - their branches only last two or three weeks. In my view that's a very long-lived branch.
Well, the OP clearly lays out the case when long-lived feature branches are better. They are great for enabling you to do things you should not do. They are good for landing huge, un-reviewable changes, or working in code bases with no tests.
Every argument I have ever seen in favor of feature branch development, and frankly 90% of the arguments in favor of git, take the form of "It makes it easier for me to [[terrible idea]]."
If you know what the fuck you're doing, you can sneak new features in just as easily as with a feature branch. Maybe even moreso.
So if you are working for an organization that is actively attempting to self-destruct, to the point where you feel like there needs to be a conspiracy to keep the wheels on, even then feature branches don't help. And in fact they make things worse because your coworkers who defect are busy breaking things on their feature branches, undoing all of your carefully laid plans to unfuck the code and thereby the organization.
Learn to refactor code that has unnecessary constraints into code that doesn't. Then those features you can't get out of the backlog become 3 weeks instead of 3 months, and you can actually work on them, because you've already made the change easy.
Yeah, I'm not saying there is never a need for a long-lived feature branch, there are use cases. I would say it's fairly rare in practice for it to be preferable, at least in my experience.
Once someone pointed out to me that these dynamics are the bargaining phase of loss, I couldn't unsee it. All this rationalizing is people not wanting to admit that merging is hard (most of the people who really want feature branches are also the people I categorically and empirically cannot trust to do merges properly.) They are trying to avoid dealing with their problem by making it everybody's problem.
I don't even like the 4 business day feature branches we have. When we were rapidly developing we saw all sorts of merge problems. It only works now because the commit rate has dropped off, and the chances of merge problems are somewhere between quadratic and factorial.
This doesn't mean you should look for a trouble and not prevent potential problems with better coordination / planning and carefully weighting the pros / cons of a particular decision. Merge conflicts and huge refactorings can sometimes have nasty consequences in a form of huge release delays, bugs and inconstancies surviving for months and even years after the "stable" release.
Would you be happy if someone asked you to merge 3 long lived branches, the first one being a complete UI redesign, the second one complete UI translation and the third one - complete refactoring? Maybe I am exaggerating but sometimes I have experienced things that were not very far from that.
You can enjoy the benefits of both approaches by adopting trunk-based releases. In our experience, we make small pull requests (like short lived feature branches) on GitHub, each focusing on a complete feature or a segment of it.
GitHub Actions automatically test these pull requests and create temporary environments for further testing. If all tests pass, the code enters the merge queue and gets released as soon as it's merged into the main branch. We release every commit, keeping the main branch's release log tidy. We also use a mono-repo and implement caching, ensuring that only the modified code gets packaged and released.
Long lived means gigantic. It’s not a bad idea if you have a decent test suite. But if you don’t have one it’s too risky and can easily get out of control.
Maybe there is a middle ground, such as creating "v2" (or whatsoever) folder with the newest changes where you can easily switch between the old and the new functionality.
Trunk-based development = putting unfinished work in the team's shared branch.
Feature-branches = finishing your work first.
Anyone who's ever completed a complex PR knows how much plans change over the course of the work. Obviously those immature stages shouldn't be shared with the team, let alone be in main, whether behind feature flags or not.
The main observation of CI/CD is that problems don't get better by avoiding them. If something sucks, you either need to figure out how to stop doing it ever again, or grow callouses.
The draw of feature branches is the same draw as quarterly or yearly releases: People don't know how to decompose problems into stand-alone subproblems that they can tick off one at a time. The solution is the same here. Don't avoid decomposing problems. Do it every week until you figure it out.
Another practical issue with trunk-based development is that most code review tools only support reviewing complete branches and don't support reviewing a bunch of individual commits. Well, Jetbrains Upsource supports it, but unfortunately that has been canned by Jetbrains.
However, trunk-based development allows high-paced development of applications, and testers can easily review the combined result on a test environment.
Why would you want to review individual commits when the same lines can change from one commit to another? It seems like more work. Personally I want to see the final list of changes when I review, and not waste my time with intermediate stuff.
I know some people are diligent about using rebase to present a clean commit history, but that's rare in practice in my experience. And it's incompatible with devs who aren't skilled at git.