jack: (Default)
[personal profile] jack
I talked about this several times before, but the idea was still settling down in my head and I don't think it made a lot of sense.

Imagine each commit had one parent that was the "branch" parent or "this is a logical atomic change" parent or the "the tests still pass" parent, or the "space not time" parent. All the same guarantees you'd expect from code on the same branch hold (eg. compiles, tests pass). This represents history the same way a non-branching source control history does, a list of changes that sum up the current state of the software. Or, for that matter, the same way a heavily rebased clunk-free history does. It shows the code being built up.

And each commit may have none or one (or more) "content" parent or "rebase" parent or a "chronological" parent or a "meta" parent, that represents "the change made in this commit, is based on this other commit".

If you already merge from branch into trunk, you may find the parents are quite like this already.

Why might you want to do this? Well, to me, the good reason is that it does away with all the "oh no I want to rebase but I already pushed". The pre-rebase history is just always there by default, though you could choose to purge those commits if you wanted. So any software working off your remote, when it pull-rebases, can just automatically move anything that was built on top of your pre-rebase branch onto your post-rebase branch, just as if you'd committed a few extra commits without rebasing anything. And the new code isn't just suddenly in limbo, anyone can check that the branch tip is the same as the pre-rebase branch tip.

It also may provide useful hints for merging avoiding duplicated commits, when there's extra info about which commits are "the same" other than their content. It doesn't solve the problem, but it may help some of the time your source control program can't automatically fix it.

It also removes all the "oh fuck, I screwed up, reflog, reflog, flog harder!" if you accidentally screw up a branch you're working with. Instead of the previous tip of the branch floating in limbo hoping you'll retreive it, the previous branch history, all of it, is retained, until you explicitly delete it. You don't even need to be on the same computer, someone else can ask you can push the changes and sort out your mess, when you can't (I think?) push a reflog.