Non-compiling commits make bisecting harder, when the goal is to find the commit that broke the build or a specific test. IMHO having to skip over non-compiling merge commits only makes bisecting take more time, and it may also "pollute" the test pipelines if all commits are going to be built.
Additionally, merging and fixing the merge in separate commits makes it much hard to revert a merge later, in case it turned out that the merge introduced something unwanted).
So I will always recommend doing the merge and fixing the merge in the same commit. Ideally this produces a squash commit that can easily be reverted later when needed. This makes the merge process more time-consuming, but it can help to keep the builds more stable, and to more easily track which commit (merge) introduced a particular problem.
I don't think this would apply, as I'd be merging from `dev` > `feature`, resolving conflicts, and then doing a single clean no-conflict merge back from `feature` > `dev`. That's the only commit you'd need to revert to undo the merge.
(or on a new, third, `merge` branch, if you don't want to pollute the `feature` branch with commits from `dev`)
I admit the non-compiling commits might be a problem in some workflows, but `git bisect skip` is the solution to the only problem I've ever had with it.
It's kind of a problem if the compile/build step takes rather long. Then you want to avoid having any additional non-compiling revision to check when bisecting.
But I agree in general, if the compile/build turn-around times allow for it, then a single no-conflict squash merge back into devel is definitely a very good approach to have clean and compiling commits, and for identifying the commits/merges that break the builds.
I upvoted you for the sheer uniqueness of that workflow (almost a decade using git, never seen anything like that), but I think if I ever had to work on a git tree that did that I would throw a fit ...
There is so much wrong with that approach. Kills bisects, kills diffs, kills signed commits, kills merge automation.. Yikes.
I forgot to mention that the conflict resolution commits would be occurring on the feature branch (or a 3rd branch), not on the main dev branch, if that makes it easier to grok.
Anything merged into `dev` would be a single clean no-conflict merge commit that compiles. That eliminates any merge automation issues I've encountered, although other systems might require every commit to compile.
`git bisect skip` fixes bisect, just like any other non-compilable commit on a branch.
You say it "kills diffs", and that may be true for some aspects of a command-line diff. But I find the main place my team is "diffing" is via the web view of a Pull Request. This workflow makes it possible to see the diff via the PR. Each commit shows you exactly how the conflict was resolved. Without this workflow the conflict resolutions are essentially hidden from the web view of the PR and leads to the "hidden code" issue I mentioned in the OP. (Although some newer PR views may now make this possible.)
That sounds horrible, squash -> rebase -> fast-forward merge... Much more easier to reason about the commits/changes.
Git bisect is really important in some cases and that needs all/most commits to be compilable..., especially big merge commits.
Unless you have a special reason to preserve all commits as they were made (eg. signed commits), in that case go with the linux model of small single responsibility merges that preferably have no conflicts...
Then, in the next couple commits, fix each conflict via a normal commit that mixes and matches "mine" and "theirs" as needed + deletes the markers.
Each resolution commit is independent of the giant merge commit, and can be separately diff'ed and code reviewed via the github PR or any other tool.
Also easier IMO to make the complicated resolution you want, or reset back to a previous resolution attempt without messing up the entire merge.
The drawback is that some commits won't compile, but compilable mid-branch commits are not something that I view as a goal.