This is related to the conversation about squash that happened last week.

Basically, the moment two or more people try to work on something outside of the trunk line of code (trunk/master/whatever), there is no version of their commit history that will be pretty, and so squashing the branch at the end seems like a good idea, even though it produces objectively worse code over the long run.

To wit: There comes a point where the branch and merge structure of the code N months ago is no longer relevant to my day. However, the contents of 'blame' could contain code from years ago every time I use it. [edit] How it was merged is irrelevant. When it was merged, by whom and with what commit message is what survives into the future. By squashing the who and the message are lost. But we think that's okay because it's a lesser evil than having a bunch of commits in trunk. Which is bullshit.

What's hard to stomach is a bunch of merge commits back and forth and back again, and so I sympathize with people eager to sweep those under the rug. But at the same time I know that one of the most common ways a bug makes it into the code is via a bad merge. Keeping them is more honest even if we don't want to think about all the little human things we do that make our code worse.

I want to tell one little white lie with the code: I want to pretend like Joe and Tim wrote their entire feature after my bug fix and before Steven's, even though they worked on it all week. I want them to be able to commit it as a single transaction but with all the intermediate steps.

When I say 'parallel history' I mean I want Joe to be able to rebase the branch on top of my changes, without having to go apologize to Tim for making his snapshot into mincemeat.

Or, I want us to stop pretending like feature branches fix all of our problems, with no serious consequences. Maybe we should just go back to the roots of Continuous Integration and merge on every commit, and rely on things like feature toggles and test automation to control the reach of our in-progress changes.

I think the real issue at hand here is the one-size-fits-most mentality we maintain. As a maintainer of a FOSS project I want to reserve the right to reject contributions out of hand. If I don't like your code I tell you no and you go away. I will also enjoy getting medium units of work that were a team effort without ever having to coordinate with any of those team members. As a volunteer effort, this scales like nobody's business. But just because it's working great for open source doesn't mean it's the rational answer for commercial code.

In commercial code, all changes can be tracked to either human error or a requirements change, and knowledge of the project often is locked in someone's head because archived public forums aren't the dominant form of communication or negotiation. When, how, and why every line changed matters because every fix I undo while making another one alienates a paying customer. So verifying why the code is the way it is now is fairly important.

And let's be perfectly honest here. If, as your dev lead, I don't like the quality of your contribution, guess what, it's going in anyway. I can push back and make you do it better, but 9 times out of 10 your change is going in. Maybe not today, but soon, unless I'm in the process of getting you fired for incompetence. So being able to drop it on the floor at no cost to me isn't really a useful feature. For Linus that and an insulting email are how he 'fires' bad contributors. As coworkers our relationship would be a little more complex.

Pretending that these constraints fit the exact same development pattern as what works for Linux, NPM, Mocha, or probably even Docker is just nuts. We can share a lot of tools, but we can't use exactly the same development process. And Git bends in one direction but has no give in the other.