Unless you go in with a byte editor, you can’t change Mercurial’s commit history. I didn’t say “fabricate”, I said “change”.
You can, as you say, configure your user name and email to be “Linus Torvalds” and change your computer date and fabricate whatever history you want. You might also be able to go in with a byte editor and fiddle bits and change history that way; Mercurial provides no blockchain-like cryptographic guarantees. But, unlike git, rewriting history is not supported by Mercurial; history is immutable. Rebase doesn’t change history; the commit index only ever increments. Squash and rebasing create new commits, and there history of what happened is always in the repo.
There’s a distinct and clear difference between Mercurial’s immutable history and git’s de jour history rewriting, which can literally - with the git command - change published history to make a commit made 3 years ago look like it was committed by someone else. The git workflow used by the kernel team, and the b4 tool, use this history rewriting in the standard workflow.
If you wanted to do the same thing with Mercurial, you’d have to get a byte editor and start hacking the on-disk format, and it would have to be entirely outside of any Mercurial tooling. And there is some sequential hash verification you’d have to work around, even if it’s not cryptographically auditable.
The point is, with Mercurial it would be hard and the result would be utterly incompatible with any other clone of the repo: there would be no way to propagate your changes to other clones. With git, this is a standard workflow.
Unless you go in with a byte editor, you can’t change Mercurial’s commit history. I didn’t say “fabricate”, I said “change”.
In git you also cannot change history of a commit. You can only create a new commit with a new history. You’re arguing about semantics which don’t change the end result.
The point is, with Mercurial it would be hard and the result would be utterly incompatible with any other clone of the repo: there would be no way to propagate your changes to other clones. With git, this is a standard workflow.
As the example under discussion demonstrates, it’s also impossible to propagate the changes to git clones. Since history changed, merging the pull requests shows all the differences. That’s how Linus noticed the issue.
How exactly does Mercurial manage to keep you from getting in trouble while changing history?
Mercurial actually keeps track of something called phases. Every time you push changesets to another repository, Mercurial analyses the phases for those changesets and adapts them if necessary.
There are three phases, each resulting in different behaviour:
secret: This phase indicates that a changeset should not be shared with others. If someone else pulls from your repository, or you push to another repository, these changesets will not be pushed along.
draft: This is the default phase for any new changeset you create. It indicates that the changeset has not yet been pushed to another repository. Pushing this changeset to another repository will change its phase to public.
public: This phase indicates that a changeset was already shared with others. This means changing history should not be allowed if it includes this changeset.
Mercurial uses this information to determine which changesets are allowed to be changed. It also determines how to select changes to rebase or histedit automatically. For example: using histedit without any arguments will only show draft and secret changesets for you to change.
You can not change history for any published changes - like I said, doing so makes your repository incompatible with any other clone.
It is not standard workflow in git to change the commit history for a branch on the remote. You have to use --force, and the next time someone pulls they also have to --force their any local tracking branch to follow the remote. Every git guide on the internet warns against pushing a rebase for this reason.
Locally you can do whatever. I’m not familiar with Mercurial, but I assume it must work the same as git: I can do whatever I want locally, and only what I push matters. And when I’m doing stupid stuff locally as I organize my changes, rebase is handy.
Yes, it rewrote history, and thanks to Git’s robustness it was extremely easy to notice and identify. Forced rewrites are not an issue if you trust people on your repo, and if you don’t (and honestly you shouldn’t, everyone fucks up), you can disable force rewrites in the remote
Unless you go in with a byte editor, you can’t change Mercurial’s commit history. I didn’t say “fabricate”, I said “change”.
You can, as you say, configure your user name and email to be “Linus Torvalds” and change your computer date and fabricate whatever history you want. You might also be able to go in with a byte editor and fiddle bits and change history that way; Mercurial provides no blockchain-like cryptographic guarantees. But, unlike git, rewriting history is not supported by Mercurial; history is immutable. Rebase doesn’t change history; the commit index only ever increments. Squash and rebasing create new commits, and there history of what happened is always in the repo.
There’s a distinct and clear difference between Mercurial’s immutable history and git’s de jour history rewriting, which can literally - with the git command - change published history to make a commit made 3 years ago look like it was committed by someone else. The git workflow used by the kernel team, and the b4 tool, use this history rewriting in the standard workflow.
If you wanted to do the same thing with Mercurial, you’d have to get a byte editor and start hacking the on-disk format, and it would have to be entirely outside of any Mercurial tooling. And there is some sequential hash verification you’d have to work around, even if it’s not cryptographically auditable.
The point is, with Mercurial it would be hard and the result would be utterly incompatible with any other clone of the repo: there would be no way to propagate your changes to other clones. With git, this is a standard workflow.
In git you also cannot change history of a commit. You can only create a new commit with a new history. You’re arguing about semantics which don’t change the end result.
As the example under discussion demonstrates, it’s also impossible to propagate the changes to git clones. Since history changed, merging the pull requests shows all the differences. That’s how Linus noticed the issue.
Did you read the same thread I did?
Looks like Mercurial can change the history just fine using the hg command. You just need to enable it first.
https://book.mercurial-scm.org/read/changing-history.html
Git can also be configured to disable history rewrites.
https://stackoverflow.com/questions/2085871/strategy-for-preventing-or-catching-git-history-rewrite
So the difference between git and hg really just comes down to the defaults.
You can not change history for any published changes - like I said, doing so makes your repository incompatible with any other clone.
That’s the same on Git.
It is not standard workflow in git to change the commit history for a branch on the remote. You have to use
--force
, and the next time someone pulls they also have to--force
their any local tracking branch to follow the remote. Every git guide on the internet warns against pushing a rebase for this reason.Locally you can do whatever. I’m not familiar with Mercurial, but I assume it must work the same as git: I can do whatever I want locally, and only what I push matters. And when I’m doing stupid stuff locally as I organize my changes, rebase is handy.
Read the thread. The Kernel maintainers use b4, which rewrites history.
Mercurial does not work like git, and history is immutable: there are no commands for changing history.
Yes, it rewrote history, and thanks to Git’s robustness it was extremely easy to notice and identify. Forced rewrites are not an issue if you trust people on your repo, and if you don’t (and honestly you shouldn’t, everyone fucks up), you can disable force rewrites in the remote
I’m responding to the literal words you said that were inaccurate. Cheers.