I have to admit I've never understood the point of keeping the history linear.
I have to admit I've never understood the point of keeping the history linear.
A True Scotsmans non-history-destroying version control system would reveal and be able to replay every single editing keystroke that went into a change.
If your workflow is single branch all PRs merge into main then of course you want to rebase since the only thing that matters to your history is "when did this batch of changes land in main"
But that's all local stuff. It doesn't matter if you delete something nobody else ever saw.
Branches are very often passed around to other people, examined and validated in that form. Rebasing a public branch loses some amount of important history. And even for private branches, if you rebase multiple commits at once then the testing you did between those commits gets invalidated.
Fossil allows you (for example) to fix typos in the commit messages of published branches, safely and in a way that does not destroy history and propagates cleanly with "sync". It allows you to modify the DAG safely, and in a way that does not destroy history and propagates cleanly. It does this by providing special tags that when added to a commit change the check-in comment, or branch name, or parents of the commit. The original immutable check-in is preserved, but for display purposes, the tags can override some properties of the original check-in.
Real example from just this morning: Last last night I mistakenly merged the wrong way. I merged the reuse-schema branch into trunk, rather than merging trunk into the reuse-schema branch. When I saw the problem this morning, I was able to fix it, even though this mistake had already propagated to other repositories. The change entered the DAG as a supplemental "correction" tag, so no history was lost, and if in 20 years somebody wants to go back and figure out what happened there, they can, because all information is preserved. But for day-to-day viewing of history, it looks as if I had done the merge correctly to begin with.
And I really am curious: why preserve the incorrect merge? What scenarios involve needing that information, why is that ever a good thing? If the default view of history doesn’t present these preserved mistakes, how is that really different from a rebase?
I’m also troubled by the language about “immutable” history and “destroying” history. Git doesn’t destroy any history. When you rebase, it creates a new branch. The old one is still there. You can get it back. The only reason it goes away is because it gets garbage collected later, because the user chose not to have anything pointing to it.
When I was in high school, I was taught that if I worked as a bookkeeper and I make a mistake, I should never erase the mistake. Instead, draw a line through the mistake, notate what is wrong, and enter a correction. To erase an entry in the financial ledger of a company is fraud. It is a felony. Making a correction is fine. But do not erase. Always preserve an audit trail.
I believe that VCSes should be treated similarly. While you are assembling a change, you can make as many erasures and corrections as you like. But once you commit the transaction - once you check-in the change - it then becomes part of the permanent record. To alter that transaction after the fact is akin to felony fraud. Sure, mistakes happen. By all means, correct the mistakes. But the original mistake and the correction should all be part of the audit history.
If you want to say that commits to your private branches are not part of the permanent record, and that you should therefore be permitted to edit those private branches, then I think you have a stronger case. That does not come up as much in Fossil. Fossil does support private branches, but they are seldom used. The usual case in Fossil is that all check-ins auto-sync up to the parent repo.
Shunning is not quite the same. Shunning is a mechanism for removing illegal are illegitimate content. Shunning is sometimes required to comply with legal mandates. But it is not a part of day-to-day practice. Shunning is an exception - and escape valve - undertaken only in an emergency.
Most organizations' repositories will have one or more protected branches (e.g. master). What is published there remain. Even mistakes. When the history on those branches are erased it is for very good reasons only. Usually it involves the size of the repository getting too big, illegal / private content and paths only differing by lower and upper case messing with Git on Windows. Even in those very rare cases the history of the vast majority of the files remain. And this is also something all CVS has to face so this is not specific to Git itself.
Dev branches are pushed, overwritten and erased. I don't see how that's a problem. In the end having small intelligible commits that reads like a dish recipe accelerates code reviews and corrections and I haven't seen any other VCSes doing that as efficiently as Git.
If you're using git, everyone has a local repo, and that repo's master branch is local: they can rewrite their unpublished content in it however they want. It's really quite convenient; a good feature of git.
If you commits the result of a merge before doing anything with it to fix it up, that implies that you will sometimes be committing non-buildable code which still contains conflict markers. That's not even allowed under a continuous integration policy that every build has to build (and pass unit tests and whatnot).
Git doesn’t erase mistakes. It presents a second, separate graph of commits after rebase than before. Both graphs are still there, nothing is erased, and nothing is destroyed. It’s quite important, as a VCS, that nothing is destroyed because it means if I do it wrong, I can undo.
> To erase an entry in the financial ledger of a company is fraud. It is a felony. […] I believe that VCSes should be treated similarly.
You want people who fix code mistakes to go to jail if they don’t keep a record of the mistake? Why? There’s a very, very good reason that actually lying on financial ledgers is illegal, while quietly fixing a merge mistake is not. You are conflating so many things in this broken analogy that it’s difficult to respond to.
Financial ledgers are one of the very few things in the world where history is required by law to be sacrosanct, and companies know this and agree to it in advance. The number of editable things in the world that aren’t expected to preserve history and aren’t illegal are uncountable. Nobody’s going to jail if they erase a bad chapter in a book or movie script. Nobody’s committing a felony if they tear down a house and rebuild it. Nobody is being called a deceitful liar when they erase a mistake on their math test and write down the correct answer.
Your belief was not shared by the designers of git (nor of any other DVCS before Fossil). This is the core of why your claims about git are wrong. No promise was ever made to preserve history as it happened, that was never part of the intent in its design. Therefore the very argument that git is being deceitful is a dishonest argument - it’s a projection of your personal goals onto other people and other’s people’s software, not a true story about why git was designed the way it is. The fact that your telling is motivated by trying to convince people to use Fossil over git just makes the hyperbolic framing seem extra cheesy.
> If you want to say that commits to your private branches are not part of the permanent record, and that you should therefore be permitted to edit those private branches, then I think you have a stronger case.
That is, in fact, the primary use of rebase, by a mile. I’m certain you already know this. Which is a big part of why all the hyperbole about fraud, lying, deceit is ironically not an honest narrative.
> Shunning is a mechanism for removing illegal and illegitimate content.
So is rebase. Sometimes that’s how it’s used. Maybe it happens, but I’ve never seen public history intentionally rebased other than in emergencies.
So what, exactly, is preventing people from using shun for legitimate content day-to-day? Are you policing it’s use?
Are you actually unable to engage in a significant discussion without using strawmen?
"it should be a felony" is definitely a strawman.
You are presuming to speak for @sqlite by claiming they did not mean felony, when the very example they provided of what it means to take it seriously is that it’s a crime.
What makes you certain that they weren’t suggesting exactly that?
I don’t think it’s fair to call my question a straw man. @sqlite has been making a strange moral argument out of git rebase for many years. I honestly want to understand where it’s coming from.
Fwiw I also don’t think it’s fair to ask a bullshit adhominem straw man question like “Are you actually unable to engage in a significant discussion without using strawmen?”
Stop it stop it stop it.
Stop it.
If it the program is open source, you're legally entitled to have an FTP site where only the current version of the files is available, and yesterday's version is gone. Moreover, you actually don't have to have yesterday's version retained anywhere else. Obviously, that will cause problems for you.
In between that extreme, and the other extreme (every little thing being fastidiously recorded and immutable) are rationally workable alternatives that allow reasonable mutation.
As an employed developer or contracting consultant, you may be required to adhere to certain version control practices as part of your contract. If that doesn't rule out revising history, you can revise history.
This is probably one of my biggest problems with fossil. It is very opinionated about the workflow you use. My typical workflow involves making many commits on a private branch while working on something, many of which won't be able to build or pass tests, and then clean everything up before pushing to a publicly visible branch. This allows me to easily roll back if an approach ends up not working out, or cherry-pick smaller changes to other branches if a change ends up being needed in multiple feature branches in progress at once, etc. With git that sort of workflow is trivial, with fossil, it might be possible, but it doesn't fit with fossil's blessed workflow.
Git on the otherhand is pretty flexible, and can be used for a lot of different workflows, and doesn't push you towards a specific one.
The context & argument you’re repeating here but either missing the true essence of, or teasing about, is the view that since git rebase edits commit history it is bad. The Fossil devs have long been advocating this view using hyperbolic language like saying git is ‘lying’. This unfortunately incorrect framing stems from Fossil having different goals and assumptions than git, and the Fossil devs projecting their dogmatic views on their perceived competition.
But… even the Fossil devs are not actually advocating capturing every single keystroke.
The point is people talk about rebasing and squashing a commit with a typo, and then people argue against this because it's "rewriting the history". But, as you say, why would anyone ever want to capture that typo?
He did because AFAIK he's an extremely nice guy who gladly suffers fools; I guess that's for ideological reasons, and that's his choice.
I found your own participation in the whole ordeal deeply insulting. But, again, that's me exclusively. I'm just a happy Fossil user.
Look, I think it’s absolutely great if you like Fossil. And I also think it’s great if Fossil has immutable history and cares about it deeply. My beef here is with saying that git rebase is a “lie”, being “deceitful”, “fabricating” things, etc. That is an untrue claim, it’s ironically itself completely dishonest.
If you like Fossil and want others to use it too, it might be worth reflecting on how Fossil’s marketing pages are actually pushing some people away from trying it. That’s what the claims about git really are: marketing.
The dogma that allows someone to go around calling others a liar over the tools they use to write code is what’s deeply insulting, and Dr. Hipp has had far, far more influence already than I ever will. You can stand next to this dogma if you like, but I think you’ll be on the wrong side of history. For now, blind followers everywhere like to parrot the claim that git rebase is a lie, without being equipped to defend this idea because they don’t actually share it deeply and haven’t been thoughtful enough on their own to understand the implications.
Thus why would anyone ever publish bad versions of private commits in an anonymous, unpublished branch that were locally rewritten N times?
Meanwhile, you project your disdain towards Fossil in your own hyperbolic comments and the use of intentionally divisive words like "perceived competition". Fossil is not competing with anyone.
> Fossil is a distributed version control system (DVCS) written beginning in 2007 by the architect of SQLite for the purpose of managing the SQLite project. Though Fossil was originally written specifically to support SQLite, it is now also used by countless other projects. (Fossil docs)
I'm not speaking for the Fossil project, but I'd bet that the only undesired consequence of Git's existence in their minds is the unfortunate phenomenon of ocasional Githeads stumping into Fossil's forums, foaming in the mouth about how Fossil is All That's Wrong in the Universe and how its existence is unbearable unless they change it to be more like Git.
Yeah, I can use hyperbole too. How nice!
False. This page is proof. https://www.fossil-scm.org/home/doc/trunk/www/fossil-v-git.w...
> I’d bet that the only undesired consequence of Git’s existence in their minds is the unfortunate phenomenon of ocasional [sic] Githeads stumping into Fossil’s forums
Wrong again, you lost that bet. You owe me a beer. https://www.fossil-scm.org/home/doc/trunk/www/rebaseharm.md You need to actually read the Fossil pages first to understand what this argument is even about. You are providing evidence that you’re just attacking me without understanding the history.
> I can use hyperbole too.
Do you realize that you’re totally validating my whole argument? Because you’re calling my argument hyperbole and a straw man, when I’m accurately describing what Fossil and it’s author have said about git rebase, without realizing it you are agreeing with me and disagreeing with @SQLite. You claimed that my question about rebase being a felony was a straw man, when in fact that’s exactly what @SQLite said literally. You called @SQLite’s idea ridiculous, not mine. You are disagreeing with the core belief that Dr. Hipp holds that modifying code history should be at the level of a criminal offense.
I’m upvoting you because you are proving my point.
I don't see how that helps the problem.
One of git's goals is to record the history of a project, and one can argue that that feature can be improved.
I think recording every typo would be worse, as it becomes harder to find the edit you're looking for. More hay covering the same needle.
I don't think rebasing is a bad feature, but I think merges and branches in the history provide o more useful story of how the code was written.
If a branch is public and is merged, then we need to preserve the original and track the relationship.
Git is fundamentally broken with both rebase and merge.
If we consider a branch which has a single commit, then rebase and merge achieve something very similar. The text is merged and a new commit is created. The target branch head is updated to point to that commit, which has the previous head as its leftmost parent.
The merge version will record two parents, whereas the rebase (actually a cherry-pick under the hood) records only the destination branch parent. This omission is unfortunate for the rebase.
What people do when rebasing an already published commit is put something in the commit message like "Cherry-picked from <SHA>", which really wants to be a parent pointer in the meta-data, so that it shows up under "git log --graph" and such.
On the other hand, if we merge multiple commits, rather than rebase, another idiotic thing happens: a single, squashed commit gets created out of the merge result and planted into the target branch.
We need a flavor of git rebase which records a parent pointer for every single cherry-picked commit. That will create a merge which makes sense. Merge a feature branch with 7 commits, and you get 7 individually merged commits, each with a parent. (Or, maybe you will just get six: perhaps one of them became obsolete and was skipped.)
Also, if commits have additional parent pointers, then any editing workflows involving rebase should preserve them. Say I locally merged the foo-feature branch into master. I now have 7 new unpublished commits coming from the merge. But, uh oh, the merge was actually bad. While textually it went fine, something is wrong and needs to be fixed up. Say I need to reach for interactive rebase to manipulate these 7 commits; maybe adjust something in the third one. This interactive rebase job should preserve the above-described parentage.
BTW, Fossil has commands called “shun” and “scrub” that do effectively rewrite history. Every version control system has them, because you have to have them. Being on a high horse over rebase is 1- not going to change rebase, and 2- makes it seem like you don’t fully understand git, and it’s design decisions and goals, therefore not qualified to opine on it. See Chesterton’s Fence.
All of this is mostly irrelevant to getting coding done. Wanting immutable history is fine, if that’s what you want. I’ve never heard a compelling reason to need it, and it’s not one of git’s goals, and never was. (Nor was it a goal of any other version control system either, not of svn or p4 or hg or source safe…) Git is version control, and it does what it was designed to do which is keep multiple versions around, let you share versions with other people, and be a safety net against code loss. I can’t think of a single time in my decades of professional software career where it mattered that someone edited their local history before pushing, and/or didn’t preserve some strange sacrosanct history of the exact order every line of code was written. I don’t have anything against holding this goal, but I’m unconvinced that it’s relevant.
> I don’t have anything against holding this goal, but I’m unconvinced that it’s relevant.
I am likewise not convinced of the value of immutability.
I see the git repository as an object being edited, and that object has no history of its own. When we add a new commit, say, we are making a new version of the whole git-object which now has some new objects in it, plus a moved head.
The old git repo in which that head pointed to the previous commit doesn't exist any more. Well, some people have copies of it. They can stick with those, or get this one. Take it or leave it.
We should be able to control any aspect of our work. If I want to rewrite thousands of commit messages in the published master branch, that's my privilege. Git deals with this just fine; someone who fetches that is informed that their master is divergent by thousands of commits. They can disagree with what I did and then just cherry pick things onto the original branch going forward.
Bisect, blame, and log, among other features, are all easier to use with a linear history. They’re not unusable with non-linear / many branches, just easier linear.
I’m not quite sure I understand your comment though - it implies that you consider linear history to be a strange and/or non-default thing to do. What’s the implied point of not keeping the history linear, or what is your preferred workflow? I’m not entirely sure what’s being compared, but linear is the default you get from more than 1 commit. Linear is very natural with a team of one or only a very small number of people. Linear is a lot nicer than branchy for branches that have exactly 1 commit.
> I’m not quite sure I understand your comment though - it implies that you consider linear history to be a strange and/or non-default thing to do.
Sometimes you get a branch, I get them even on personal projects if I forget to push and work on a different computer.
I've heard people say that, when they do get a branch, they will rebase to make the history linear instead of having a merge. I don't think that is default.
That wouldn’t make the complaint invalid though.