Remix.run Logo
ngruhn 4 hours ago

Maintaining linear history is arguably more work. But excessively non-linear history can be so confusing to reason over.

Linear history is like reality: One past and many potential futures. With non-linear history, your past depends on "where you are".

    ----- M -----+--- P
                /
    ----- D ---+
Say I'm at commit P (for present). I got married at commit M and got a dog at commit D. So I got married first and got a Dog later, right? But if I go back in time to commit D where I got the dog, our marriage is not in my past anymore?! Now my wife is sneezing all the time. Maybe she has a dog allergy. I go back in time to commit D but can't reproduce the issue. Guess the dog can't be the problem.
psychoslave 3 hours ago | parent | next [-]

That’s also because there are multiple concerned that are tried to be presented as the same exposed output through a common feature. Having one branch that provides a linear logical overview of the project feature progression is not incompatible with having many other branches with all kind of messes going back and forth, merging and forking each other and so on.

In my experience, when there is a bug, it’s often quicker to fix it without having a look at the past commits, even when a regression occurs. If it’s not obvious just looking at the current state of the code, asking whoever touch that part last will generally give a better shortcut because there is so much more in the person mind than the whole git history.

Yes logs and commit history can brings the "haha" insight, and in some rare occasion it’s nice to have git bisect at hand.

Maybe that’s just me, and the pinnacle of best engineers will always trust the source tree as most important source of information and starting point to move forward. :)

hnarn 4 hours ago | parent | prev | next [-]

> So I got married first and got a Dog later, right?

No. In one reality, you got married with no dog, and in another reality you got a dog and didn't marry. Then you merged those two realities into P.

Going "back in time to commit D" is already incorrect phrasing, because you're implying linear history where one does not exist. It's more like you're switching to an alternate past.

ngruhn 4 hours ago | parent [-]

The point is that it's harder to reason over.

hnarn 4 hours ago | parent | next [-]

I don't really agree that it's harder to reason over in the sense that it's hard to understand the consequences, but I also agree that a linear history is superior for troubleshooting, just like another comment pointed out that single squashed commits onto a main branch makes it easier to troubleshoot because you go from a working state to a non-working state between two commits.

agumonkey 4 hours ago | parent | prev [-]

there are others tricky time issues with staging/prod parallel branching models too, the most recent merge (to prod) contains older content, so time slips .. maybe for most people it's obvious but it caused me confusion a few times to compare various docker images

fc417fc802 3 hours ago | parent [-]

> the most recent merge (to prod) contains older content

Can't that also happen with a rebase? Isn't it an (all too easy to make) error any time you have conflicting changes from two different branches that you have to resolve? Or have I misunderstood your scenario?

fc417fc802 3 hours ago | parent | prev [-]

You omitted the merge commit. M is taken so let's go with R. You jump back to M to confirm that the symptoms really don't predate the marriage. Then you jump to R to reproduce and track down the underlying cause of the bad interaction.

Had you simply rebased you would have lost the ability to separate the initial working implementation of D from the modifications required to reconcile it with M (and possibly others that predate it). At least, unless you still happen to have a copy of your pre-rebase history lying around but I prefer not to depend on happenstance.

ngruhn 2 hours ago | parent [-]

> Had you simply rebased you would have lost the ability to separate the initial working implementation of D from the modifications required to reconcile it with M

I'd say: cleaning that up is an advantage. Why keep that around? It wouldn't be necessary if there was no update on the main branch in the meantime. With rebase you just pretend you started working after that update on main.

fc417fc802 an hour ago | parent [-]

For the reason I stated that you quoted right there. Separating the potentially quite large set of changes of the initial (properly working) feature from the (hopefully not too large) set of changes reconciling that feature with the other (apparently incompatible in this example) feature. It provides yet another option for filtering the irrelevant from the relevant thus could prove quite useful at times.

Recall that the entire premise is that there's a bug (the allergy). So at some point a while back something went wrong and the developer didn't notice. Our goal is to pick up the pieces in this not-so-ideal situation.

What's the advantage of "cleaning up" here? Why pretend anything? In this context there shouldn't be a noticeable downside to having a few extra kilobytes of data hanging around. If you feel compelled to "clean up" in this scenario I'd argue that's a sign you should be refactoring your tools to be more ergonomic.

It might be worthwhile to consider the question, why have history in the first place? Why not periodically GC anything other than the N most recent commits behind the head of each branch and tag?