upvote
I thought this was how everyone worked.

I wish it were :)

This is the right way to do it. Whether using trunk-based development, git-flow, etc -- you're controlling the flow of merges in a particular direction.

However, I think the "larger planning issue" is harder to easily avoid when you have more devs, more changes, or the AI-boosted output we have today. If feature B requires feature A, and feature A isn't up-to-date with main, I could rebase feature A to main, then feature B to feature A. When feature A is merged and we're ready to PR feature B, I can rebase to main again then make my PR.

reply
That sounds like a lot of work. If you rebase A on main then B on main, you end up having to resolve A's conflicts on main twice. But if you stick with merge commits, A's conflicts are handled once in the merge from main.
reply
Yeah, I absolutely never run into this problem.

Sometimes we will have a huge stack of changes one of us is "finished but not clear to merge".

either:

- We just swap ownership of the branches and eng 2 now commits directly in branch 1. We review the final content together and typically pull in a 3rd person to review our combined work. Eng 1 either pairs with eng 2 until its finished or starts on a task that is decoupled from those changes.

- We use an integration branch that gets threated like the temporary master branch until the feature is ready to merge.

reply
when you're not just doing small patches (like Greenfield work), and you have multiple developers, it can be unreasonable and wasteful to do what you describe. say we're redoing the way memory management it being done, or changing a foundational api. A and B could go through master, but they'd have to redo a whole bunch of work. Or we could make an integration branch where A and B hash things out together and only push to master when their work is done. you can also see how this allows a lot more back and forth about the places where the designs interact rather than 'I got in master before you, so you get to eat a multi-day merge and I'm outta here'

this kind of interaction shows up more in a 'release' based model than CI environment, and one where the cost of testing is non-zero (because we're actually doing testing). I know that's not a very popular model, but not all software development is CI websites.

reply
Those big refactoring should be discussed with the whole teams so everyone understands how they’re going to be affected. And rework like this should probably be hidden behind an abstraction (to do it gradually).
reply
yes of course they should, that doesn't mean that integration branches aren't a good way to manage the tactical process. and often this kind of situation comes up when you're trying to do exactly that, introduce that abstraction that solves a whole bunch of issues, but requires cross-cutting changes.

the problem comes up the other way too. the person making the refactor can get stuck in a perpetual hell of constantly reapplying the changes to smaller deltas that are being committed daily to master.

reply
I don’t remember which books exactly, but it was about legacy code. The author was talking about seams. If you’re trying to complete a refactor in one go, it will usually be arduous and maybe fail. What you want is to find seams in the codebase and maybe create some, where you can gradually decouple the architecture. After that you’ll have contracts and independent modules that can be reworked.

It’s not easy though and you need to have a very good understanding of the codebase. But the nice thing is that you can do it without having to maintain a long lived branch (which is an antipattern).

reply