> Out of curiosity: Was this also with TeamWare/SCCS?
Yes. It was quite primitive by comparison to git, but it worked.
> > If you care about history, what you really want is to see what's changed over time, and that is always linear. At time t_n you have some commit, and at t_n+1 you have some other commit, and so on.
> Depends on what the history should represent or what you care about specifically, or optimize for.
> What landed in the integration branch or was deployed to a singular test environment is certainly linearily ordered on the time scale. What happened during parallel development is rather a DAG. (And even there you could have different working models: clean up (e.g. with git rebase), then integrate; or keep every commit ever made (even if hidden in presentation), fossil-style.)
At Sun if you had a bug fix you did the equivalent of clone, commit, <any number of fetch and rebase operations>, push.
But for large projects we did something very different. We had a clone of the upstream (OS/Net) for the whole project, and developers would clone the project and work on that. Every few weeks (two or four, depending on the project) the project's gatekeeper would rebase the project clone onto the upstream, and then all the developers would rebase their clones onto the project clone. (Think `git rebase --onto`.)
When a project completed successfully it would rebase one more time onto upstream and push.
These clones functioned as branches. They were archived, but in the upstream there was no evidence left of the clones' existence -- certainly there were no merge commits, as those were verboten.
As you can see, there was no complex DAG in the upstream: it's all linear. The history of the clones was mostly irrelevant, though if really cared (sometimes I did) you could go look at the archives.
> However, with rebasing on top (or squash-merges) you lose the commits in their original context.
Why should anyone care about that "original context"? The project/bugfix delivered. Between the upstream's HEAD as just before delivery, and after, are just the differences contributed by that push, and the commit messages for the commits in that push, and the deltas in each of those commits, are all the context you need.
> You may have no merge-commits, but all your commits are merged commits.
So what?
> (They only have one parent in version history, but the file content is the result of a merge, be it automatic or manual.)
This is like caring about seeing every typo or braino the developer made while working on that code. It's just not useful. Once the code is pushed upstream the conflict resolutions that the author had to do will never again matter to anyone else.
If you wanted to investigate what went wrong in a mishap -a mismerge- you can: examine the downstream clone's history (including reflog). If nothing went wrong, you're done. You can archive those downstream clones (or the relevant bits of their reflog), which, again, we did at Sun precisely for this reason.
If you use a merge flow, those merge commits are forever, and they will forever pollute the history and complicate rendering of history, and they will remain long after anyone could possibly care about what might have gone wrong in a mismerge.
> This may no big deal for things you can and do test for. If finding out a bug later however, it is often easier to comprehend, if one can see or test, if that happened only while integrating the changes. Then you have at least still the working version from the tip of the branch available for comparison.
Ok, so you're concerned about investigations. Again, they're rare, and there's a way to do them without polluting the upstream's history.
Perhaps there could be something like merge commits that aren't commits but annotations that are not part of the Merkle hash tree and which can be deleted, or which are in the Merkle hash tree but hidden, and where if you want to find out the details of what the developer did you still have to go dig in their clones. But IMO that's still mostly pointless.