I wonder what the server feature gives you. I've been using fossil for a decade or so, always over ssh. Definitely don't need to do that setup part.
Fossil doesn't do rewriting history. I think that rules it out for large team efforts. As an immutable distributed log of everything I write by myself it's essentially perfect.
You can definitely fake it. It’s probably not worth it though. Fossil’s workflow might prove lovely without the need to rewrite, but if not just use a tool like git that allows it.
What I like about this question, however, is what it reveals about our assumptions, and what it says about what the words “commit” and “history” mean, and what it is we want out of a version control system.
The truth is that a commit is what I say it is, whether I’m using git or Fossil or anything else. This means that it’s absolutely always guaranteed to be subjective, and has only the meaning I give it. Preventing rewrites might have some workflow benefits, I’m quite open to the idea that there are advantages to the way Fossil does things. But the idea that rewrites should be prevented in principle because history should be preserved is really very funny to me. It’s only possible to preserve the history of the things I said are history in the first place.
You can definitely fake it if determined, it's sqlite under the hood. Your way would work but the branch will live forever (possibly closed) if you push it from the local repo.
Easier is to copy the repo, do a bunch of feature work there, then rsync over to the shared repo and commit. I don't bother though, local history has the mistakes and backtracking enshrined.
Private rebasing to clean up a series of commits before pushing anywhere, for one. While there’s a genuine distinction to be made between private pre-merge history and published post-merge history, Fossil’s stance is that no amount of pre-push cleanup should ever be allowed, that code commits should be immutable history from the moment of inception.
Right, you’ll definitely think twice about committing early and often if commits are suddenly etched in stone. Feels like the wrong incentive/message for a VCS. That said, I believe Fossil may be better equipped to explore a presentation layer that users have control over, and separately examine commit history when needed. Git wasn’t designed that way. I don’t agree with Fossil’s dogmatic stance on git, but Fossil might be workable in the sense that your history of noisy throwaway work can be mostly muted. I think?
I take it the smiley means you know this, but to be clear, that’s not the kind of rewrite we’re talking about. Fossil is against providing multiple/alternate sequences of commits that can represent the same timeline. Breaking the Merkle tree isn’t even in consideration (because a determined adversary can just as easily break Fossil). The discussion is really over workflows and perceptions, and has very little to do with the technicalities of preserving history.
Squashing literally requires `git rebase`. Perhaps you think of squashing as a GitHub button and not a series of rewriting commands? Technically, any rewrite is equivalent to some arbitrary construction of history from some point in time, but I think a reasonable definition of rewriting history is if you need to rebase or cherry-pick when using the command-line.
We don’t need a reasonable definition of rewriting history, we need a better conversation about what our tools are even for. Git isn’t a tool for preserving history, it’s a tool for keeping track of code changes.
Git rebase provides a new, second, altered sequence of commits. It doesn’t replace the original. We often choose to preserve the rebased sequence, but this distinction is not academic, it’s critically important because as a part of a version control system, rebase can be undone, precisely because it does not write over the old history.
Git never promised a “history” per se, not in the form of an immutable record of events. The framing of git rebase as a history rewrite, the very idea that rewriting history is bad, came from the Fossil team in an attempt to convince people to try Fossil and cast shade on git. I’m in favor of better VCSs, but the claim that rebase is a history rewrite is hyperbolic, and the judgement on top of that is silly and misguided. Rebase is a tool designed to reorder a sequence of commits, mostly for the purposes of making local changes presentable before pushing them, and has other legitimate uses too.
> rebase can be undone, precisely because it does not write over the old history
Good point. Perhaps "rewrite history" is not the best metaphor, and does not cover all possible git workflows. I only considered the workflows where a rebased branch is merged back onto master instead of its non-rebased variant, which loses its name, its remote copy/copies and is eventually hit by the GC.
> the very idea that rewriting history is bad, came from the Fossil team in an attempt to convince people to try Fossil and cast shade on git.
The resistance I've met among developers to adopt rebasing workflows with git have no knowledge of Fossil.
My impression is that the main objection to such workflows is that it exceeds some developers' novelty budget [0] and that those developers generally don't read git messages and don't value the history of code to understand its current shape.
Sorry maybe I got a little ranty there. Rewrite history is an okay metaphor, not great but nothing super wrong with it as an approximation. And you're totally right, there is definitely resistance to rebase outside of Fossil, and even within the git community with people who've never heard of Fossil. Git does have a steep learning curve and a bumpy interface that most people (including yours truly) never get all the way through.
FWIW, my intro to rebase came after using Perforce for years. Because git is strict about commit ordering and P4 is not, I was struggling to figure out how to manage multiple in-flight changes like I would in P4, and how to clean up and push something that wasn't a hot mess. Rebasing my local workspace, it turned out, is the answer to that. It is the key to working around git's strict commit parentage, and makes it easy to sculpt changes so they're palatable for me and my team.
Above I was referring to some of the anti-rebase messaging Fossil has put out in the past. Some is there still, for example https://www.fossil-scm.org/home/doc/trunk/www/rebaseharm.md I'm quite pleased to see that a lot of the most hyperbolic verbiage is gone now, it used to carry on quite a bit. But that page still says rebase is "dishonest", which is a deeply ironic claim, if you catch my drift. That kind of mis-representation ruffles my feathers a little bit, but I've had discussions with the Fossil team right here on HN about it, and they have in fact been open to listening, responsive, and willing to change and improve the messaging.
Technically, they are: you erased commits from your history. You created a single new commit with equivalent contents, but the timeline has been altered, and if you previously pushed to your remote you now have to force push because the remote remembers a version of history that no longer happened.
Fossil heavily discourages (outright forbids?) this kind of stuff.
Technically, commits are not erased after squash/rebase. They remain there and available to use unless they are not reachable from a named branch for like 90 days. Technically, the timeline is not altered, but the commit sequence is altered. Git does not offer an immutable timeline, and thus squash & rebase cannot break it. Fossil does try to discourage rewrites, but does offer ‘purge’ which is a rewrite, because of course, forbidding all rewrites is impractical.
I saw this was downvoted and tried to help by upvoting, but it is worth talking about what “history” means though. Squash commits rewrite the source branch history, but they don’t rewrite the destination branch history.
I would argue the team-wide destination branch history is what should be called “history”, and the only thing that matters. But Fossil’s distinction is more rigid and it considers anything ever committed to be history.
Squashing a local branch does, in a way, rewrite local commit history. But this shouldn’t be called “rewriting history” in my book. Rebasing the main branch really is fully rewriting history (and this isn’t a squash commit). Squashing a feature branch that multiple people touch is somewhere in between. It’s a little rewriting. It’s often desirable. Should squashing small feature branch PRs be called “rewriting history” in the sense that Fossil claims that it’s intended to misrepresent the project? I don’t really think so, but since “rewriting history” wasn’t clearly defined, it’s open for debate.
You don't even need to rewrite the source branch history. You can leave the source branch as is, and create a single commit on the main branch that is the squashed content of the source branch. It isn't considered a merge in the normal way by git, which can cause issues, but there is no lost history and GitHub and gitlab are able to keep track of the source of the squash commit.
Yeah true! It still goes to clarifying what people mean by the words “history” and “rewrite”, etc. The primary public history of a feature branch might only be preserved in the merge commit, so in some sense the preserved history is different than the branch history. It’s somewhat fair to call that rewritten. I prefer to focus on the fact the git never promised a “history” at all. Git doesn’t offer to capture what happened accurately, it only promised to keep the content of your changes and its relationship to the preceding state of the content. It only promised a sequence of dependent commits, and it allows reordering commits by design.
ahh, right, thanks for the responses. I was confusing not being able to rewrite history on remote branches with not being able to rewrite history at all. I rewrite it locally all the time but almost never remotely.
fossil has the concept of shunning an artifact, this has the interesting side effect that that artifact will now never be allowed in the repository(without additional work to un shun it).
"Purge" is really only intended for use with fossil's "bundle" feature, bundles being essentially feature-rich patches which record all of the historical state of the bundle. (Yes, it's long been flagged as experimental, but it's also been unchanged since it was added so i'll look into getting that notice removed or amended.)
The idea of fossil's bundles is that a person not associated with a project can submit a patch in the form of a bundle, a developer imports that bundle into their repo and either retains it or "purges" it, leaving the developer's repo clone back in a clean pre-bundle state. That feature can, however, and sometimes is, used for "popping" the top-most commit from a repository (so long as it has not yet been pushed to a remote). So long as a local repo has not been synced with any remotes, and so long as there are no branch points to interfere with it, repeated applications the bundle/purge combo can be used to pop the top-most checkin multiple times, effectively wiping out as-yet-unsynced changes even if they span multiple checkins.
Fossil doesn't do rewriting history. I think that rules it out for large team efforts. As an immutable distributed log of everything I write by myself it's essentially perfect.