> So is it a lie that sometimes after lunch on a Friday, the act of programming is often a series of off-by-one, off-by-two, off-by-one-the-other-direction compile-test-edit-commit loops?
No, exactly the opposite: it's a lie to pretend that you can write perfect code the first time, and it does no-one any favours in the long run: not yourself, and certainly not those who come to learn from you in the future. And it's not normal or expected the way makeup can sometimes be; junior programmers will be genuinely deceived and this will cause real harm.
Keep the history, warts and all. Best case someone might learn something from it. Worst case you're no worse off.
The “keep everything” approach conflicts with the “have clean commits” approach. If we keep everything, instead of “Build A; Build B; Build C” we wind up with “Build some of A, B, and C;” * 8.
But again, like the parent comment said, if you’re never rewriting history, that means you’re stuck with how the code was actually developed, which frequently is not that clean. Many people don’t write three separate features most of the time, they write three features together and at the same time.
If the real history is that you developed all three features in an interleaved way, isn't that more useful (e.g. for bisection) than a fictional history that you haven't actually tested? Most likely your cherry-picking/rebasing won't be perfect, so you'll still have parts of A mixed in with B and C and you'll have things like one commit depending on changes from a future commit. The history of how the code was actually developed might be "messy" but it's more likely to at least compile (because presumably you were compiling it from time to time while you were developing).
Why would my messy history be useful for bisection? The places I committed, it may not have even fully compiled except for the very last commit. In that case, to separate the code in a useful way (such as 3 commits, one for each feature, each of which compiles on its own), you'd have to do a bit more work and create new commits, which again means either rendering the original commits pointless or disregarding them.
Surely your test-edit cycle involves at least some compiling. Maybe not every commit will compile, but most changes that compile will have a commit. At the very least a "real" commit has a much higher chance of compiling than an "artificial" one that you constructed retrospectively.
If you really do make most of your commits not compile then I can sort of sympathise with squash-merging, but if you merge then worst case it's a one-liner to bisect while only looking at "mainline" history (i.e. only the merges to master, the equivalent of what you'd get if you'd squash-merged), whereas if you squash-merge then there's no way to bisect back through the original history.
Compiling vs. not-compiling is only the tip of the iceberg; there’s a lot of other aspects of my development that don’t make sense until the very end. Arguably, the whole feature is basically useless until it’s finished; why would I keep working on it in any meaningful way after it is complete and running? If that happens, chances are that the ticket wasn’t atomic enough. There are exceptions of course, such as substantial rewrites for bug fixes, but those are by nature not the norm. As a result, my commit messages are only for me, which saves time in development. Commit messages “wip” and “working now” mean something to me, but definitely hold no value to whoever is doing a git blame in the future, which is another benefit of squashing.
If it compiles then I can use it in an automated bisect, which is the main thing VCS history is useful for IME. I'm a big believer in "refactor mercilessly" and "make the change easy, then make the easy change", so while obviously the final feature will not be working in the intermediate commits, the work will touch on other code areas and there's always the possibility that this will introduce a subtle bug that slips past the current test suite, and if that should happen then I want to be able to bisect down to the smallest possible diff before I start trying to understand it manually. I also find that a small commit with a useless message is actually a much more useful blame result than a big commit, even if the big commit contains a detailed explanation of the overall change.
> I also find that a small commit with a useless message is actually a much more useful blame result than a big commit, even if the big commit contains a detailed explanation of the overall change.
That's pretty interesting. I know with me, that is definitely not true, because 90% of all commits would just be the message `wip` which makes Git Blame incredibly hard to use.
What are you trying to get out of the blame? I do sometimes git tag --contains to find the overall feature that the blame-output commit was part of, but most of the time the most useful thing is just to see the diff for that commit or frankly even just the list of files it touches.
Much of the time it’s asking what the motivation behind a line of code is, such as why we take some crazy convoluted approach to what seems like it should be a simple task. Editor plugins such as Git Lens display the blame output so it is much more convenient if that information is in the commit rather than in an associated tag.
No, exactly the opposite: it's a lie to pretend that you can write perfect code the first time, and it does no-one any favours in the long run: not yourself, and certainly not those who come to learn from you in the future. And it's not normal or expected the way makeup can sometimes be; junior programmers will be genuinely deceived and this will cause real harm.
Keep the history, warts and all. Best case someone might learn something from it. Worst case you're no worse off.