upvote
An important addendum: code can sometimes, with a bit of extra thinking of part of the reader, answer the 'why' question. But it's even harder for code to answer the 'why not' question. Ie what were other approaches that we tried and that didn't work? Or what business requirements preclude these other approaches.
reply
> But it's even harder for code to answer the 'why not' question.

Great point. Well-placed documentation as to why an approach was not taken can be quite valuable.

For example, documenting that domain events are persisted in the same DB transaction as changes to corresponding entities and then picked up by a different workflow instead of being sent immediately after a commit.

reply
I don't think this is enough to completely obsolete comments, but a good chunk of that information can be encoded in a VCS. It encodes all past approaches and also contains the reasoning and why not in annotation. You can also query this per line of your project.
reply
Git history is incredible important, yes, but also limited.

Practically, it only encodes information that made it into `main`, not what an author just mulled over in their head or just had a brief prototype for, or ran an unrelated toy simulation over.

reply
In fairness to GP, they said VCS, not Git, even if they are somewhat synonomous today. Other VCSes did support graph histories.

Still, "3rd dimension" code reasoning (backwards in time) has never been merged well with code editing.

reply
> In fairness to GP, they said VCS, not Git

I did say VCS, but I also don't know what Git is missing in this relation.

> Other VCSes did support graph histories.

How does Git do not?

> Still, "3rd dimension" code reasoning (backwards in time) has never been merged well with code editing.

Maybe it's not perfect, but Git seems to do that just fine for my taste. What is missing there?

reply
> Other VCSes did support graph histories.

Yes, git ain't the only one, but apart from interface difference, they are pretty much compatible in what they allow you to record in the history, I think?

Part of the problem here is that we use git for two only weakly correlated purposes:

- A history of the code

- Make nice and reviewable proposals for code changes ('Pull Request')

For the former, you want to be honest. For the latter, you want to present a polished 'lie'.

reply
> - A history of the code

Which is a causal history, not a editing log. So I don't perceive these to be actually different.

reply
Not really. Launchpad.net does not have any public branches I could share atm as an example, but Bazaar (now breezy) allowed having a nested "merge commit": your trunk would have "flattened" merge commits ("Merge branch foo"), and under it you could easily get to each individual commit by a developer ("Prototype", "Add test"...). It would really be shown as a tree, but smartness was wven richer.

This was made possible by using a DAG for commit storage and referencing, instead of relying on file contents and series of commits per reference. Merge behaviour was much smarter in case of diverging tip or criss-cross merges. But this ultimately was harder and slower to implement, and developers did not value this enough and they instead accepted the Git trade-offs.

So you seamlessly did both with a different VCS without splitting those up: in a sense, computers and software worried about that for us.

reply
I am not quite sure what you are describing here. Git's underlying commit graph is a DAG.

You can use different, custom merge-drivers (or whatever it's called) for Git to get the behaviour you describe here.

reply
Certainly, but merges are treated differently by default, and getting to this sort of output would require "custom" tooling for things like "git log".

Whereas bzr just did the expected thing.

reply
You can select whether you want the diff to the first or the second parent, which is the difference between collapsing and expanding merges. You can also completely collapse merges by showing first-parent-history.

Or I do not understand what you mean with "the expected thing".

reply
If you throw away commit messages, that is on you, it is not a limitation of Git. If I am cleaning up before merging, I'm maybe rephrasing things, but I am not throwing that information away. I regularly push branches under 'draft/...' or 'fail/...' to the central project repository.
reply
Sure, but you are still supposed to clean things up to make the life of the reviewer easier.

There's an inherent tension between honest history and a polished 'lie' to make the reviewer's life easier.

reply
The WIP commits I initially recorded also don't necessarily existed as such in my file system and often don't really work completely, so I don't know why the commit after a rebase is any more a lie then the commit before the rebase.
reply
The "honest" historical record of when I decided to use "git commit" while working on something is 100% useless for anyone but me (for me it's 90% useless).

git tracks revisions, not history of file changes.

reply
Sounds easier (for everybody) to just use comments.
reply
You put past failed implementation in comments? That sounds like a nightmare. I rather only include a short description in the comment that can then link to the older implementation if necessary.
reply
But why would you ever put that into your VCS as opposed to code comments?

The VCS history has to be actively pulled up and reading through it is a slog, and history becomes exceptionally difficult to retrace in certain kinds of refactoring.

In contrast, code comments are exactly what you need and no more, you can't accidentally miss them, and you don't have to do extra work to find them.

I have never understood the idea of relying on code history instead of code comments. It seems like it's all downsides, zero upsides.

reply
Because comments are a bad fit to encode the evolution of code. We implemented systems to do that for a reason.

> The VCS history has to be actively pulled up and reading through it is a slog

Yes, but it also allows to query history e.g. by function, which to me gets me to understand much faster than wading through the current state and trying to piece information together from the status quo and comments.

> history becomes exceptionally difficult to retrace in certain kinds of refactoring.

True, but these refactorings also make it more difficult to understand other properties of code that still refers to the architecture pre-refactoring.

> I have never understood the idea of relying on code history instead of code comments. It seems like it's all downsides, zero upsides.

Comments are inherently linear to the code, that is sometimes what you need, for complex behaviour, you rather want to comment things along another dimension, and that is what a VCS provides.

What I write is this:

    /* This used to do X, but this causes Y and Z 
       and also conflicts with the FOO introduced 
       in 5d066d46a5541673d7059705ccaec8f086415102.
       Therefore it does now do BAR, 
       see c7124e6c1b247b5ec713c7fb8c53d1251f31a6af */
reply
Both have their place. While I mostly agree with you, there's a clear example where git history is better: delete old or dead or unused code, rather than comment it out.
reply
Good naming and good tests can get you 90% of the way to "why" too.
reply
Agreed. Tests are documentation too. Tests are the "contract": "my code solves those issues. If you have to modify my tests, you have a different understanding than I had and should make sure it is what you want".
reply