I think you're confusing workflows with commit history.
You can work with feature branches all you want, rebase them as you feel like it, and then do squash merges to main.
The likes of GitHub even have a button for this.
Assumption: above mentioned total noobs don't use git rebase -i or equivalent, everyone else does
In 25 years of professional development I’ve never really had a situation where the commits on a branch would have helped me understand what was going on a year ago when the work was done. That includes pretty big bits of project work.
I’d much rather have a trunk with commits at the granularity of features.
I've had separate commits come in handy several times when `git blame`ing when working with people who actually described what changes were about in their commits (which, unlike comments, don't go out of date).
Coincidentally, every single squash-merge commit advocate I've had the unfortunate debate with was a regular practitioner of public tmp / tmp / try again / linter / tmp / fix / fix / haaaaaands commits.
Note that I'm not against squashing/history rewriting e.g rebase -i and stuff (which I'm a heavy user of so as to present sensible code aggregation reviewable per-commits), only squash-merge.
A ticket should be atomic describing a single change request. PR in this case are the working room. It can be as messy or as clean as you want. But the goal is to produce a patch that introduces one change. Because if you would rebase -i at the end, you would have a single commit too in the PR.
A typical bugfix branch might look like this after rebase -i:
Move property to a more appropriate place
Improve documentation of feature Foo
Fix accidental O(n^2) in feature Bar
Fix interaction of Foo with Bar
TN 43 - Fix mismatched interface between Foo and Bar
We've moved the X property to a more appropriate place and
improved the documentation for Feature Foo. We've also found and fix
an O(n^2) implementation in feature Bar.
The the ticket TN-43 will have all the details that have lead to the PR being made: Bug reports, investigations, alternative solutions,...The commit message is what's more important. I don't think I've ever needed what is in a merged branch. But I've always wanted the commit at one point to have tests passing and a good description of the patch. And all the talk in the engineering team are always about ticket. It does makes sense to align those.
I prefer granularity at a product or team level decision. Not workflow details.
With GitHub you can squash any PR merge. The link to the PR will include the complete history of the feature branch prior to the merge. Even the commit history prior to force pushes is tracked.
I chunk my changes into tiny commits ("linter"/"tmp"/"wip"), but then rebase aggressively, turning it into a set of logical changes with well-formed commit messages. git bisect/revert work great with history written in this way even years layer.
But: most of the people I've been interacting with also produce lots of "wip"/"tmp", but then skip the rebase. I can only offer my help with learning git rebase for so long before it starts taking too much time from the actual work. So squash it is: at least it produces coherent history without adding thousands of commits into `--ignore-revs-file`.
> I chunk my changes into tiny commits ("linter"/"tmp"/"wip"), but then rebase aggressively, turning it into a set of logical changes with well-formed commit messages. git bisect/revert work great with history written in this way even years layer.
In a PR based workflow, it has become easier to have the PR be a logical unit than to `rebase -i` all the time on my end.
What has happened a whole lot though is the exact opposite.
As such, a new codebase is likely to grow by large unwieldy commits and a mature one by targetted small commits.
The other thing to say - that is missing from this conversation - is that if you’re using github, the original commits are still against the PR.
I strive to do that when making commits for work too, and that helps when going back in history and looking at history to motivate why a change was made.
While working I rebase all the time to move changes into the relevant commit, I don't find that particularly hard or time consuming. Doing this upfront is easy, splitting commits after the fact is not.
I consider this standard practice, at least in the sector I work in (industrial equipment control software, some of which is considered human safety critical).
It's less about reviewing commits from a year ago, than making change low-risk today. And small commits can easily be rolled back. The bigger the commit, the more likely rollback will be entangled.
It better to have partial features committed and in production and gated behind a feature flag, than risk living in some long-lived branch.
You're not addressing the problem. You're just wishing that the problem wouldn't happen as frequently as it does.
But that's like wishing that race conditions don't happen by making your allocations at a higher frequency.
Also, your comment reads a little bit as a non sequitur.
My professional experience contrasts with yours. I've even worked at a company where commit history and PRs were so central to understand and explain changes that PRs were even used as the authoritative sources on how to implement features and use frameworks.
Maybe different in other places, but after 15 years in my codebase, I’m still happy with a simple linear history.
Why would you not want to squash merges? It's one of three options offered by GitHub in their PR merge buttons.
They create a linear commit history, which is what you want when you have to audit changes.
> except to clean up messy mini-branches written by total noobs.
Nonsense. You get a messed up commit history as easily as when you create a PR in GitHub, and after team members merge their commits, you click on GitHub's "update branch" button.
You also get a messed up commit history if you merge a PR after someone else merged theirs.
You will always mess up your pristine commit history if you have more than one person posting and merging branches. With one notable exception: squashed commits.
This constraint is usually enforced by code review.
On Github, the unit of code review is the PR.
Therefore, I prefer squashing.
It is, and that is some bullshit. The only sensible way to work with that is to break up larger features into several PRs - which is often positive anyway, but sometimes it doesn't fit the nature of the change.
But my point is, is that I believe the important thing to preserve in history is whatever your unit of review is. If you could stack PRs and each were subject to the individual review, I would not combine and squash those (just the individual commits within each PR).
I do not share that belief, but this thread (your posts and others) gave me an idea about code reviews. They became commonplace when I'd been working in software for a while already and, while I see the benefits, I never really felt like I handled them well. I guess one of the ingredients for handling them better is to center the workflow around them - an area in which I have never noticed major changes in an existing project, although they are visible when looking from the right angle: Long-lived, large feature branches have become noticeably less common.