In my opinion squashing is all you need. You keep the organic history on the original branch and the clean and easy to follow history on the master branch. Ideal would be to have a “collapsing” commit instead of squashing for ergonomy.
Another benefit of not squashing is it encourages devs to think about their commits and is a great opportunity to document what you are doing when they are doing it. If you are squashing 10 commits with junk commit messages (because devs know there is little value in having meaningful commits in what will be a squashed branch), trying to summarize all the changes into a meaningful commit message is hard. It can be valuable to see the intention of atomic commits in git history. The squash branch on merge strategy is just lazy and is counterproductive to having meaningful git history.
This depends on the assumption that going to the trouble of making a carefully curated commit history well documented is even worth the trouble. Sometimes it might be, but I don't think it's a given.
> The squash branch on merge strategy is just lazy
"Lazy" is the negative way of saying "easy" or even "more efficient". "Lazy" implies that the other way is better. Is it? Maybe sometimes.
Am I "lazy" if I walk on my feet instead of my hands? It really is a lot easier.
I prefer to add commentary in the PR on the final changes - what does it do, how does it work, what are some pieces of code I'm less sure of, etc. It is accessible since the squashed commit gets linked to it and that provides a place for people to ask questions.
Also is a lot faster to write and easier to communicate compared to messing around with moving code across commits, ensuring tests pass across them, etc.
Basically I think people care more about what was built and how it works rather than how to split it up step by step (although if the latter is important I can add a comment for that on the PR - although ideally it would have been separate PRs.)
I think the problem is that often the order you want it in a clean history is not exactly the chronological order it was developed. Eg you may build out a feature vertically, tweaking the interfaces between the components as you go along. But a clean, atomic git history would probably introduce each component in a finished state in separate commits.
>- are easier to debug (and possible to bisect; it's not possible to bisect a squashed commit).
In practice, if bisecting indicates a commit caused the problem you can narrow it down further by checking out that branch and investigating further within that branch (which ideally isn't too large). Also, if you have a highly structured PR then you may need to be careful to ensure that each individual commit passes CI.
At that point you might as well ship each commit via a separate PR. (While in development you can temporarily set the branch for Part 1 as the base for Part 2.)
You're assuming it is not an old bug and that the branch is somehow kept around for other developers to re-open months or years later.
A PR for each commit seems overkill. Usually a PR is for a feature, but code-wise, a feature might require several atomic changes. For example: prepare configuration, move files around, add tests, add new code, delete old code, refactor. Each of those could be a separate commit, bringing you to a polished feature with test coverage.
Might depend on how companies use git but I just verified I can see commits for PRs from 2017 in my work codebase; could bisect that if needed (although code likely is no longer relevant.)
I think splitting PRs into multiple commits can make sense when there are only 2-3 commits but you're right that it doesn't when there are more than that.
> At that point you might as well ship each commit via a separate PR. (While in development you can temporarily set the branch for Part 1 as the base for Part 2.)
Absolutely. Indeed, this (independent commit) is a very positive side effect (typical example: separating refactoring commits).
git log --first-parent shows the merges but not the complete history of each merged branch. git log --first-parent --patch displays all the changes that came with a merge as if it were one big squash commit (in general git log --patch diffs trees, not single commits).