I liked the thorough article, but my goodness did they beat around the bush w/regard to their actual contribution to this process (per the title).
I think the short version is: they made `git-cinnabar`, which is a git-to-hg translator, to help git users interact with the Mozilla repos.
----
One contribution I can make:
> For reasons I don't know, Mozilla decided to use separate Mercurial repositories as "branches".
Originally, separate clones was the recommended way to do "topic branches" in Mercurial (not to be confused with "named branches"). There was no direct equivalent to git's branches. Eventually, Mercurial got 'bookmarks' which basically closes that gap, but that only became a core feature in 2011, well after these Mozilla repos were established.
----
Aside: I prefer Mercurial myself, and I hope to keep using it for personal projects until I die (:
> Aside: I prefer Mercurial myself, and I hope to keep using it for personal projects until I die (:
One of my favorite stories happened three or four jobs ago... at this job I kept a giant whiteboard that I had swiped from a conf room, behind my cubicle. And whenever anybody asked questions we put it up on the board. We were an SVN shop and someone had asked how Git worked and I was like "do you want me to explain Git, which is harder to understand, or Mercurial, which is basically the same but a little easier if you're coming from SVN?" and they said Mercurial. So that is how for a week or two a set of sketched diagrams sat around behind me describing Mercurial.
So while that was happening, I was in the middle of some big commit, this guy Cal comes over. Cal is, we'd classify him as nontechnical but he's essentially the Product Owner for the stuff I'm building, he's the one whose workflows the software needs to enable. And I motion to him that I need 5 minutes and finish my thought and save and commit and whatever else, take off my headphones and ask "what's up, Cal?"
He has been staring at the diagram for those minutes, bored, and this non-technical user says, "okay, so let me see if I got this straight, inside some folder there's another folder named dot-h-g that is a repo..." and goes on to explain everything about Mercurial from a simple diagram, except that he can't figure out what problem it solves. And so I tell him, "you know how on fileserv everybody has to back up every file by appending a timestamp? software developers use these commits instead, so that every commit tells you who changed it and they have to say why they changed it, and that's how you save it," and his eyes kind of go wide and he's like "why don't we have this?!" and I'm like "you could! let me show you TortoiseHg..." and he really liked it, and of course then couldn't convince anybody to actually use it. (There's a problem where you really need to lock, say, an XLSX file.)
Mercurial is always to my mind the version control system that a typical nontechnical office worker could appreciate just from looking at a whiteboard diagram.
> Aside: I prefer Mercurial myself, and I hope to keep using it for personal projects until I die (:
...
> you could! let me show you TortoiseHg...
Same here. I use TortoiseHg daily and propose the occasional contribution when something breaks/can be improved. It is really a project that has been chugging away for more than 15 years now.
I liked hg a lot when I worked at a place that used it but I've since just sortof defaulted to git for my own stuff since that what everyone seems to be using.
I miss Mercurial, thankfully ToirtoiseGit is similar experience to the Mercurial and SVN clients, and like a large majority I just fix git issues by cloning from scratch as the famous xkcd comic.
> my goodness did they beat around the bush w/regard to their actual contribution to this process (per the title).
Fair point. I came up with the title first. Then as the content grew large and diluted the essence of the title, I reconsidered, but ended up sticking to it as a shameless clickbait.
> Originally, separate clones was the recommended way to do "topic branches" in Mercurial (not to be confused with "named branches").
That still leaves the question "why topic branches rather than named branches?". For the needs of the rapid release process, named branches could have been used, but weren't. I haven't tried to contact the people involved at the time to have a definite answer. It's not /that/ important, and I'm not /that/ curious.
What a beautiful post it has become nevertheless rivaling the long reads of the New Yorker and the like.
I originally wanted to go to sleep but the writing was too captivating to put down, and every paragraph was motivated, and it wasn’t stretched. It was the length it needed to be.
One of the Firefox rapid release designers here :-)
IIRC, topic branches were used because:
- Mercurial named branches were half baked at the time and I was advised against them by folks who knew hg better than me.
- We were already using separate clones for security update versions (3.5.x and 3.6.x) so we just kept doing the same. Some tooling could be reused.
- Rapid release was a big change and we didn't want to disrupt mozilla-central dev. Having rapid release in different clones got us out of the way and reduced the risk of negatively affecting development. m-c was the domain of developers, the rr repos were the domain of the release team.
> Fair point. I came up with the title first. Then as the content grew large and diluted the essence of the title, I reconsidered, but ended up sticking to it as a shameless clickbait.
I enjoyed it. It could maybe have been two posts, but it's a headline, it's supposed to get you to click on it.
One of the biggest problems with Mercurial is that they took a long time for histedit to become a usable workflow. I speculate (without any evidence, so this could be entirely wrong) that this is because many Mercurial contributors preferred MQ over editing history for local patches. (Certainly I knew many Gecko developers who swore by MQ.)
Coming from Git, with the git rebase --interactive flow coupled with the reflog to provide a backup to let you undo any mistakes, MQ was awful. Your choices were (1) allow hg qrefresh to overwrite the old contents of your patches and hope you never made mistakes, or (2) make your patchqueue an hg repo and have to look at second-order diffs. (I chose option (3)--symlink my patchqueue into Dropbox so that I could use Dropbox's history feature as a kind of poor man's reflog.) And to top it all off, MQ didn't understand three-way merge logic the way git rebase does. This workflow seems to me clearly worse than Git's tools, and I'll never understand why so many developers at Mozilla claimed to prefer MQ over Git.
Yes, I think it's under-appreciated how much git and mercurial were ideologically different in their attitudes to history rewriting.
The generally accepted narrative these days is that git became popular because of github (with the implicit assumption that was an arbitrary choice) and/or the Linux kernel (without much questioning of why people specifically cared about Linux's tooling for wource control).
But what I remember from ~2010 was a load of blog posts eulogizing history rewriting and how it allowed you to separate out the activities of committing changes locally in order to record the state of your work at various times, and assembling the final patch into something suitable for review by others.
Meanwhile mercurial took the stance that history rewriting is bad, and as a result people ended up using even worse solutions like `mq`, which is basically tooling around directories full of numbered patch files.
You still see that distinction in hg: once it eventually did realise that history editing is a desirable feature for many reasonable workflows it added a lot of additional complexity to the basic model, with features like phases (supposed to stop you rewriting commits that someone else might be depending on, but just using the proxy measure of "was this pushed to a 'publishing' repo") and "evolve" (which keeps a complete history of history rewrites; useful in principle for tools like code review systems to avoid the common pattern of putting a "patch id" into the commit message, but in practice felt like a lot of extra mental overhead).
So at least my view is that git made a "practicality beats purity" bet on history rewriting being a net good, and hg made the opposite bet, and eventually lost.
And back on the original topic, I used hg personally before I used git, and then professionally at Mozilla before git cinnabar came along (although by this point I was using git in other projects). So I've used mercurial a lot but actively prefer git when given a choice. Nevertheless I think this article understates just how good cinnabar is compared to the options that preceded it; apart from the case where you have a hg hash from an external system and want to find the commit locally (where you just run `git cinnabar hg2git`) it's basically totally seamless and just works without problems. It's a small tool that does one thing really well, to the extent that it's easy to overlook just how good it really is.
I can't speak for those other people, but as someone who likes MQ (even today!) I think one advantage is its conceptual simplicity. It's literally just patch files; you can edit them by hand if desired. For people comfortable with or used to that, I can see the allure vs. the more mysterious operations occurring in "rebase --interactive" and such. Even quilt, the MQ progenitor, is still used today (at least on Debian).
Wasn't there an option (4): using 'qsave' and 'qpush --merge' to merge two MQ series with 3-way merge support? I don't think I've every really used it, though.
But overall, yeah Mercurial was playing catch-up to Git on that front for a while. Surely didn't help adoption.
MQ was a big revelation after working for 3 years with Git. Until I faced with StGit, it was much easier to use and fill more native especially with rebases.
> Originally, separate clones was the recommended way to do "topic branches" in Mercurial
This is still what the Guide on the Mercurial site mentions as the "basic workflow" for working on separate features. Named branches are considered "advanced", and bookmarks are an afterthought entirely.
About 10 years ago, after reading a lot about how hg was more intuitive than git, I decided to give it a try. I was already using git branches a lot, so this was definitely not a good first impression.
People like to say that github is the reason git won the dvcs wars 10 years ago, but I think this is it. I think a lot of people's first impression of git back in the day was making a local mirror of their company's svn using git-svn. Without local branches this was a pointless exercise but with git you still got some benefit even without the remote being a git repository.
Back in the day I was doing some GCC development while upstream was still using SVN. At that time there was both Hg and Git mirrors, and while the GCC repo isn't that huge in the grand scheme of things, it's big enough that the "standard" hg workflow of having a separate checked out tree for every local branch you're working on was definitely painful. While I had been using hg for some personal projects, this was really the killer feature that drove me to git.
You don't make multiple forks of a project if you want to PR multiple separate changes though (github doesn't even allow it). And, on top of that, last I heard, forks in github are actually implemented as git branches. :)
Interesting, given that Google and Facebook [2], at least, eventually moved to have their repositories offered via Mercurial interface, instead of git.
I also would expect that Github eventually will also offer mercurial repos.
p.s. And let's not talk about abomination that is GitLFS (starting from the fact that it requires separate subcommand).
I just don't think there is good RoI for implementing Mercurial support. It really isn't about the interface (which I think most people agree hg is better than git). It's just the network effect: most projects use git so everybody learns git and they don't want to learn another tool even if it's better in some ways. At the end of the day, once you pay a higher upfront cost to learn the ~5 git invocations you need, your daily productivity between using git and hg is probably the same.
Google and Facebook is different: they have a unique use-case and scale, and massive internal tooling teams supporting their use-cases. Also, as an employee, you're probably more open to different VCS systems because if you learn hg at Facebook, you're learning it on company time whereas if you learn for an open source project, you're learning it on your time.
It's almost like qwerty vs dvorak in that regard, except git and mercurial were contemporaries. Mercurial isn't quite good enough to displace git, and git has Linus as a promoter which was all it needed to be the leader.
That said, I agree that the network effect of having just one is more valuable than mercurial's ergonomics (which could still use a good branch story).
Mercurial also missed the window on performance and safety. If you started using it around 2009 or so, Hg was notably slower for daily use and a lot of people recommended using extensions to match Git features but those extensions were not stable (Hg and RCS are the only VCSes I’ve seen require data to be recovered from a backup due to normal usage).
There’s a meme that Git is hard to use but I think it’s conflating the challenges of getting used to version control at all, distributed version control, and any specific tool. I watched a number of developers do that and it was about as much work to go from SVN to either Git or Mercurial, and if they learned the other DVCS it was always easier since they were mapping concepts rather than learning them for the first time. The marginal returns on productivity weren’t worth switching in most cases so it tended to come down to Git being so much faster and, as network effects kicked in, easier to host.
> There’s a meme that Git is hard to use but I think it’s conflating the challenges of getting used to version control at all, distributed version control, and any specific tool
That may be the case for some people, but far from all. Many people who started with cvs or even rcs and have moved on to the newer things as they have appeared still find got annoying and unintuitive. Especially compared to Mercurial.
You use it, because it is now the standard, but you are also very aware of how much cleaner and easier other systems have been.
My experience was comparing multople people who started with Mercurial and later learned Git, and had basically all of what people term “Git problems” with Hg because the hard part was thinking about distributed version control.
I’m not saying Git is perfect but simply that it’s hard to separate the difficulties from learning new concepts and working styles from the tool.
There was an interview with Linus Torvalds at some point where he points out that Mercurial was one of the tools he tried using to replace Bitkeeper, but found it to be much to slow. Has he tells it in the interview he later learned that the slowness he experienced was due to a bug in Mercurial and had that not been there, git might never have happened.
If that's true it a little sad, but I also wonder if many of us might still be on SVN, Perforce or whatever. Git, by being a product of Linus brought a lot of focus on Git. Bitkeeper never got the same attention, that was a commercial product, but being used for kernel development didn't see to promote it as much as I'd expect.
Bitkeeper was more or less like Subversion, fast, expensive and slightly complicated; you seem to overestimate the relevance and influence of Linux kernel use for the average corporate decision maker who doesn't care about Linux, doesn't care about distributed VC, doesn't care about performance (because it only affects peons), doesn't like to spend money and doesn't like bleeding edge tools.
We'll never know. But git being used to manage the Linux Kernel did a lot for its asendency. if Mercurial had been the choice, maybe we'd all be on Hghub instead of Github. Bitkeeper's proprietary status is what dampened enthusiasm there.
> There’s a meme that Git is hard to use but I think it’s conflating the challenges of getting used to version control at all, distributed version control, and any specific tool.
Anecdote follows!
I originally started with cvs, and then later, svn. I struggled when git came along, the workflow felt super cumbersome and I kept tripping over the 3 stage process (working directory, staged for commit, and committed), compared to the 2 stage process for already-tracked files in cvs and svn.
After several years, I still never got used to it, and kept having to google when I’d run into random weird issues, having accidentally gotten my repo into a state that had strayed from the basic happy path. Then I started using hg at work, and life got a whole lot easier.
I still haven’t migrated my personal repos off git into hg, mostly because I haven’t (looked for, or) found an hg equivalent of gitea that I can self host, but from my personal experience, day to day usage of git is way harder than day to day usage of hg.
Then again, it helps that I learned hg on the company dime, instead of on my own time.
> There’s a meme that Git is hard to use but I think it’s conflating the challenges of getting used to version control at all
No. I had used CVS, SVN, SVK, Bazaar, and Mercurial for years before I switched to Git. I can generally explain the internals of all of these tools (a DAG) to someone in simple terms in minutes. Overlaying that onto the commands becomes easy.
What Git does is take that concept and wrap it in the worst possible workflow UI. The people that immediately grafted onto the Git community cheered this on for some reason very early and then recanted by saying that you are really supposed to build "porcelain" for Git since it was meant to be a rough tool.
To this day all I see are articles about people's confusions and conniptions over simple things that Git does incorrectly because it's UI is horrible. Most can't even get to the point where they understand the DAG. Even though I know what is supposed to happen it's hard for me to fumble around with simple commands because the naming is inconsistent and I have to research to find solutions. This was rarely an issue with Mercurial and when I talk to people that have used both they seem to share that sentiment.
Git is the PHP of version control. Widely used and very popular but has a lot of architectural problems that make it a total mess.
> I watched a number of developers do that and it was about as much work to go from SVN to either Git or Mercurial, and if they learned the other DVCS it was always easier since they were mapping concepts rather than learning them for the first time.
We recently adopted a tool that uses Perforce as a backend. It's been interesting to try and describe centralized version control to younger engineers who have only used a dcvs like git.
Sure, but most of those are things you rarely need and it’s not like Mercurial was an AI which always knew what you meant - anyone who ever tried to explain merge-queues to someone else knows that some concepts are just harder than others.
I am talking of things like "opsie, I don't want to commit this yet" (git reset) and "destroy all my work" (git reset --hard) being a command line switch apart. That's just wrong. That's so wrong I keep git reset --hard safety net around, in fact. https://gist.github.com/chx/85db0ebed1e02ab14b1a65b6024dea29
Kind of like how “hg update” becomes “destroy all my work” with -C? At some point you do need to learn what things to be careful about. Git’s reflog will avoid most forms of data loss but uncommitted/staged changes are a harder problem than it might seem.
It sadly clobbers your working tree. Not calling that checkout doesn't make it any better. Nothing other than checkout ought to change the working tree -- is that too much to ask?
There are plenty other commands that change the working tree. rebase, cherry-pick, revert, merge, etc. Are you suggesting that all these should be done by checkout?
pull is fetch + rebase or merge. You can use fetch instead of pull if you prefer. Or `git remote update`, for that matter.
Yes, sorry, that was poor writing style. Git does indeed warn you that it would clobber your working tree and suggests that you do it in its behalf (the stash/pop dance).
Why is the user exposed to that? If git needs those files checked out for the merge, does it really have to be in the working tree? Why not in a hidden, ephemeral subdirectory? Leave my working tree alone, I say!
> Hg and RCS are the only VCSes I’ve seen require data to be recovered from a backup due to normal usage.
Count yourself lucky then. Git was well known for losing data, so much, that it was featured at xkcd [1]. Well, perhaps not the tool itself, but it's user interface was (more than it is now perhaps) so awkward that users often got it wrong. If you don't make that back-up, you might not even know how much you've lost.
That’s not really what that xkcd is about but that was kind of my point: it’s a long-running joke but it’s not really true – in reality Git makes it really hard to lose data, and most of the time when people say they lost data what they really meant was that they had a sloppy merge and needed help using reflog to retry it.
I’ve worked in modest sized teams within a larger organization (roughly a hundred developers) and have often been the person people ask for help when something goes wrong; most of our teams went from CVS / Source Safe to Subversion, and then Mercurial to Git, and the big step was really the switch to a distributed system - moving from Hg was largely a non-issue (things got faster, we liked GitLab more for other reasons). The only time Hg lost data was back in the era when rebase was an extension, so it wasn’t the core system’s fault but it was a source of friction.
>>This means there is no friction in adopting Git at the workplace.
It could be said that the virality (network effect) is higher as it spreads easier. Anything is opinionated it's just whether or not those opinions align with your internal values. It appears git aligns with you.
As somebody who has actually been using Sapling (because it provides a much saner UI and mental model than git), the git compatibility of Sapling is at best so-so. It feels more like a stopgap solution while they're evolving their own backend (which I'm pretty sure they use internally, because git just doesn't scale to FB monorepo size and doesn't support their rebase-on-push operation). LFS flat-out doesn't work with Sapling. Force pushing after an amend or rebase is still cumbersome, because you need to explicitly specify (again) the branch you are pushing to. And I'm not sure how bad the file descriptor problem still is that you have (had?) with large repos or submodules [1]; there was a new release recently, but I haven't actually stress-tested that.
Meta's fork/rewrite of hg, Sapling hasn't gone anywhere yet because it needs EdenFS and Mononoke that aren't yet/maybe never FOSS. It's only called hg internally because of legacy reasons but it's completely different.
Microsoft hired a git maintainer to improve large repo performance and so it's better than it was.
Sapling can use Mononoke, but it can also use Git repositories as the underlying storage layer with no server at all, and it does so by default in the OSS build. You can use it just fine with GitHub today, but there are rough edges.
My understanding is that the work to support OSS builds of Mononoke+EdenFS is happening, but there's no exact timeline right now because (from what I can tell) they basically have to abstract out and write new production storage components for the metadata/object layer, as they can't use their internal ones, obviously.
I’ve been using the sapling CLI as my frontend with github as my backend and finding it quite delightful - all the UX niceness from mercurial (and then some), while still being totally compatible with the rest of my team :)
Git has a lot of warts, but if I were to pick an alternative it would be Fossil, not Mercurial.
I believe Meta’s implementation includes server components (Mononoke) that were not open-sourced, or at least not buildable without closed-source dependencies. Same with Microsoft’s fork of git that relies on a virtual filesystem, but that one is open-sourced, if for Windows, not Linux.
Mercurial is dead unfortunately. It's been stuck on Python 2. The CLI was saner than Git but it needed Python, which helped with our (better) decision to pick Fossil instead. This was 11 years ago. It's been great, it has everything you need in a single executable which can be statically compiled.
> Mercurial is dead unfortunately. It's been stuck on Python 2.
Mercurial adopted Python 3 a while ago. Not to mention, huge chunks of it have been rewritten in Rust.
Mercurial has continued to get new features like Changeset Evolution [1] that once you use it, you wonder why all version control systems don’t have it.
Mercurial runs on Python 3 just fine and has been for a while. In fact, starting with Mercurial 6.2 (from July 2022), Python 2 is no longer supported [1].
I did not use them because I am on linux only, but I see that Matt is active and responsive, both on the mailing list and chasing bugs on the issue tracker on heptapod ( https://foss.heptapod.net/mercurial/tortoisehg/thg )
The day-to-day workflow at Meta is still using the hg frontend and regular hg commands. I would love to see the git frontend used instead, but, it hasn't happened yet.
While the real sl (Steam Locomotive) isn't installed on that many systems, I can only imagine the annoyance that it must bring to any former Facebook engineers when they assume that it's the version control
> I also would expect that Github eventually will also offer mercurial repos.
How come? That seems highly unlikely to me, especially when you consider that one of their larger competitors (Bitbucket) had Mercurial support for a long time and then removed it.
In fact Bitbucket started as a Mercurial hosting service, then added Git support, then dropped Mercurial.
From when they dropped Mercurial in 2020 [1]:
"Yesterday marked an end of an era for Mercurial users, as Bitbucket announced to no longer support Mercurial repositories after May 2020. Bitbucket, owned by Atlassian, is a web-based version control repository hosting service, for source code and development projects. It has used Mercurial since the beginning in 2008 and then Git since October 2011."
That change was so dumb. Mercurial support was the bit that put them as something different from github. Once they didn't have it anymore, why would anyone use them at all?
So since you are knowledgeable about the fact that this decision was "dumb", you must also know approximately what proportion of their users were dependent on hg for their workflow ? My priors would put it at less - likely far less - than 1%. But please share your knowledge.
In the announcement they mentioned that less than 1% of new users were choosing hg. It was probably slightly higher for old users.
> In fact, Mercurial usage on Bitbucket is steadily declining, and the percentage of new Bitbucket users choosing Mercurial has fallen to less than 1%.
FWIW I had stuff on Bitbucket from the Before Atlassian times, in Hg repos. And while I had let it bitrot a bit (too complicated to work on open source stuff with my employer at the time), once they dropped Mercurial support I saw no point in moving it to git and keeping it there so I just pulled it off and move it to github.
I'm sure I'm not the only one. The compelling story about Bitbucket for me was Mercurial.
Still seems near-sighted. If someone started a new mercurial project what would they choose to host it on? BitBucket basically automatically wins new users by being the only player in the game
Not true. I looked at the complete list of hosted projects on Bitbucket just when it was shut down and I recall that at least 10% of all repos ever created on Bitbucket were hg repos.
If i recall correctly the server/enterprise version was completely separate product written in java (as opposed to python which powered original bitbucket.com). I think the java eventually subsumed the cloud product but not too sure of that
They still have a much better PR/review workflow than github. (Imagine github if reviewing showed changes since your last review by default, and it worked, and you didn't have to make junk comments to get something to count as a review, and comments didn't get lost).
I'm sure they knew what they did. They probably primarily had git users on the service, and the motivation to use Bitbucket is most likely because you already pay for other Atlassian products.
The hosted Bitbucket and Bitbucket Server (formerly called Stash) only share the name. They are completely different implementations and Bitbucket Server never supported Mercurial.
Google currently uses a fork of Mercurial as the frontend to Piper, but there is work to replace it wholesale, eventually: https://github.com/martinvonz/jj
(As a disclosure, I'm involved with and contribute to jj, but I don't work for or speak for Google in any way; the above statement is public knowledge.)
The big idea that excites me is that it does away with the concept of having uncommitted changes. Instead, every time you save a file in a repository it is automatically committed. It is the logical endpoint of the git workflow where you make lots and lots of little wip commits and then rewrite them into a sensible set of commits later, and the whole UI is designed around making that work well rather than being something that works but constantly feels like it's off the intended path.
I completely rewrote the README recently to be more "user friendly"; does it address some of your question? I'm not trying to be snarky, I'm genuinely interested in if the README is now tantalizing enough to make you interested: https://github.com/martinvonz/jj?tab=readme-ov-file#introduc...
But in short, it has a better UX than Git by a mile while remaining interoperable at the storage level, so you can use GitHub; it has many of the niceties of Mercurial's UX like revsets, no staging area, and a templating language for log output. Conflict resolution and rebasing is clean, easy, and nearly automatic. It has features neither support, like a real undo command and "operation log"[1]. The UX is smaller and conceptually cleaner; fewer "verbs" that operate on less "nouns", so many things are more regular. It is available as an API (Rust crates) so you can extend it naturally to handle your own workflow, without monkey-patching things. You could even use Mercurial itself as a storage backend, or a custom, centralized server like Google does.
Most importantly though, its internal "automatic snapshot model" design is quite elegant and makes the design and internals very clear. And storage system is completely independent and abstracted from this, and many of the other algorithmic details (Git sort of intertwines the data model, the algorithms, and the UX in various ways.) Features like hg changeset evolution, git rerere, and rebase --update-refs are all obsoleted and naturally handled by this design, among other things.
Martin, the lead developer, also had a talk at Git Merge 2022 that covers many of the fundamentals. They're all still the same but we're evolving many things rapidly: https://www.youtube.com/watch?v=bx_LGilOuE4
[1] Yes I know about the reflog, no it is not equivalent! It only tracks changes made to visible references ("ref" "log") while jj's oplog actually tracks commands invoked, and lets you completely undo individual things in the blink of an eye, or rewind if you wish.
Lack of staging area kind of sucks.
I'd prefer the opposite - having multiple staging areas (like IntelliJ chabgelists) so I can incrementally build multiple changes at the same time.
Is there anything in jj that could be used as a substitute?
`jj split` and `jj move` are the equivalent of git's staging areas. Instead of picking which changes you want to commit, you pick which changes you want to move from the working-copy commit to the target commit you're assembling. It lets you do something very similar to multiple staging areas by having multiple commits that you're moving changes to.
Like the parent said, you typically let the "automatic working copy commit" take the place of the staging area. Really, the staging area still exists in some sense, but it's not a distinct "thing" in the UX; rather than being represented by a unique name in the tool's lexicon (the "index"), it's just represented by another commit. So, you slice and dice that commit, as you see fit.
Similarly, there is no concept of stash. The working-copy-commit model removes the need for a distinct "stash" verb, just like it removes the need for the "index" noun.
(In Git, stashes and the staging area are of course trees of blobs, just like ordinary commits. It's just that the UI surfaces them as distinct nouns.)
> This sounds reasonable but I'd like to somehow distinguish these work-on-progress commits. Is there an equivalent of mercurial commit phases?
There isn't any current notion of phases right now, but we've thought of adding them. At the moment, the main distinction added recently is between "immutable" commits and mutable ones, which is determined by a revset, and that revset by default is something like "Anything published on or an ancestor of a head in the remote." Immutable commits cannot be rewritten to a new commit ID.
Frankly I just tag all of my work-in-progress commits with 'wip:', and I use a revset to select and look through every change authored by me that isn't located in the remote main branch.
We are also thinking about improving the color and iconography of the default output to make immutable vs mutable more distinct. So we're not sure if we even need phases yet, I think...
Yup! In fact Meta’s implementation is open sourced as Sapling SCM and includes both Mercurial and Git support[1]. Internally the main repository use Mercurial although I believe a few legacy projects still use git.
From the documentation, it seems like there is 0 mercurial support. It's its own separate version control system that diverged years ago. You can either use the sapling scm client or git.
I knew the guy who wanted Google Code to be Mercurial based; he pretty much just did it because he liked Python and therefore thought anything written in Python was good.
The reason is the same as for why "fig" was done internally -- git is a DVCS that runs over a filesystem, while Mercurial has an actual protocol, so the storage layer can be plugged out. Presumably for Google Code it was some appengine or bigtable type backend. For fig, I believe it was, somehow, piper.
My understanding with the Mercurial stuff at Google is it was done that way because Mercurial defines a wire protocol, while Git does not (it expects a filesystem). So when fig was put together, they simply couldn't use git for the intended workflow, because it needed to be able to front-facade the existing CitC/Piper repository.
Prior to that, we used to use 'git5' which was kind of git bolted on in front of Piper, and it worked, but it was a little wonky with explicit import and export steps.
I tried to use fig a little before I left, and I can't say I was entirely blown away. I used to like Mercurial a decade and a half ago, and learned it before git... but it felt very foreign to me now.
I came here to mention that mercurial handles large binaries very well, wheras git LFS is a fustercluck of a workflow.
It's like submodules, where people 99% of the time have to add the --init --recursive flags anyways, and yet nobody cares to optimize the workflow.
I wish git had better submodules, and better binary asset folders that could be linked and cloned/fetched/pulled/pushed without having to have a complete checkout of the whole repository with all its history.
Oh, and automatic pruning would be nice because my git servers constantly run out of HDD space when I don't do git gc regularly, which oftentimes is broken in itself already.
I don't understand why so many people seem to dislike git. But maybe in actuality it is not many people, as usually people who are discontent are the loudest.
I used Mercurial in the past for a bit, and it was fine. But for me it doesn't seem to have any huge advantages over git, if any. And after so many years of experience using git, I know what workflows work well, how to resolve merge conflicts, how to revert to an old commit if something really gets messed up, etcetera.
I don't see any other DVCS really being able to replace git in the short run and I wouldn't be surprised if git will stay number 1 for the following decennia, as in my opinion it's really great software. A DVCS really has to provide substantial benefits over git in order to replace git as the number 1 DVCS.
Git functionality is great. But the CLI just kind of grew in a nonsensical way. No serious effort seems to have been made on UX consistency and verb/noun names.
People who've been using it for years don't notice, they don't even think about it. But when coming from scratch, it's anything but intuitive. The CLI is not discoverable in a reasonable way.
That and there's so many ways to use it.
Mercurial had the advantage of having a much more consistent UX. Though these days I'm sure I'd struggle with it, because I'm so used to git.
Mercurial was never trying to "replace" git. All of these guys came out at the same time. Git got headspace because Linux used it and GitHub was a "cool" Ruby on Rails site, run by cool web 2.0 kids, same era as the rise of Twitter, etc. (And also down all the time, just like Twitter).
Exactly this. To be perfectly honest, the git CLI is so bad that I would take pretty much anything over git. I would prefer SVN over git, despite that product being older and with less functionality, just because it's at least easy to use.
I learned and use git because that's just how the industry has moved, and I'm pragmatic enough to just roll with it. But good Lord, the UI is a case study in "programmers shouldn't be allowed to design UIs".
Yeah, SVN was terrible. Its chief advantage was it was just less terrible than CVS and carried roughly the same workflow, so wasn't unfamiliar to people. It was basically CVS with atomic commits and a better interface and transport layer. You could drop SVN into a CVS shop without ruffling many feathers -- and back then I found most people were quite resistant to "novelty" in revision control systems, so SVN fit into that.
I don't think there's anything intrinsically wrong with a centralized revision control system. I used Piper/CitC at Google for years and it could be ... tolerable. Many people just end up using git this way anyways.
But SVN shipped with garbage merge-on-merge support, and that was the deal-breaker for me.
> Mercurial was never trying to "replace" git. All of these guys came out at the same time.
Mercurial even had a couple weeks' head start on git, and git partly happened trying to replace Mercurial in early experimentation. The name "git" was always an interesting self-deprecating choice because it was (intentionally) "stupider" than its competition that it knew about, which included Mercurial (and also darcs/Monotone/Bazaar).
Essentially, the problem with git is - it is a tool that is simple in its internals, but with a complex/confusing UI. The only way for someone to feel somewhat in comfortable with git is to have a good conceptual model for how it works internally. Once you have that mental model, you feel like a magician with git, but for beginners, it is a source of endless confusion and fear.
GIT is a tool. Like a swiss army knife, it looks tricky and you need some experience to master all what it provides. But you never actually need everything and, surely, you should also shy away from features if you do not really need them. In this respect GIT is a bit like Perl or C++. You have to apply some discipline to avoid unnecessary complexity. Personally, I have never used GIT's "octopus" merge support but I am sure in some situation it may well be a useful feature to have. So I respect that while scratching my head. ;)
Those are basically all commands I am really ever using:
git status
git add
git rm
git commit
git branch
git checkout -t -b ...
git merge
Learn those and you'll mostly good to go.
Sure, I could to rebase my branches all day and make sure my version history looks "pretty" but I find obsessing with the commit history is a major source of complexity people face when using git. Another usual source of confusion is the branching model. However, that totally depends on your organization. GIT is flexible enough to support all kinds of weird development processes but if it comes over as complicated then don't put the blame on the tool but on its users.
I like the in-progress `git checkout` split to `git switch` and `git restore`. (switch and restore are still marked "experimental" in the official documentation in case their arguments change again, but in my experience they are already pretty dependable.) It's much less likely to accidentally do the wrong thing with either of the two replacements. That's one of the things that I think if that split had been done years ago there would be a lot fewer complaints about git being confusing in the base commands; `git checkout` was always an odd duck sadly (it makes sense why it was a single command from a technical sense but it probably shouldn't have ever been from a UX/DX sense).
I like it too, unfortunately it will take decades before books, tutorials and google search results can catch up.
It is the same fate as any cli application that needs to maintain backwards compatibility because it is used both by humans and programmatically as part of scripts. My favorite example of this dd. Most tutorials still show using dd against /dev/sda1 etc instead of using device names as humans should, and meanwhile people keep shooting themselves in the foot.
Although I understand all these commands and can use them, it's a typical Linux tool.
Sure, if you understand the internals you can use the tools and the horrendous GUIs that are nothing more than a thin layer of paint.
But a truly user-centric tool would actually help you with something like
"I want to work on a new Feature A"
"I want to continue working on Feature B"
"I want my changes in the software/product"
"I want to review a pull request (haha!) locally, in order to have IDE support."
"I did an oopsie and need to go back."
Imagine navigating to a website by specifing its hash, or seeing changes to a PowerPoint file using "git status" and seeing "++slide1.pp". It would be terrible.
> you should also shy away from features if you do not really need them
>Learn those and you'll mostly good to go.
I wasn't really talking about "fancy" features of git, like rebasing history to try to make your history pretty or using things like git bisect. You need to develop basic understanding of git internals, even in the most basic workflow.
I would argue that your list of commands is not in any way complete for being "mostly good to go". At the minimum, you also need to know `git clone`, `git push`, `git pull`, `git fetch`, `git diff`, `git log`, `git blame`, and `git reset` as well. You need to save progress on your current feature branch to context switch to review some PR or analyze some production bug, well add `git stash` to the list. Your boss asked you to hotfix your recent commits onto the release branch? Better not forget `git cherry-pick`.
That brings us to 17 commands (up from the 7 you listed). Fine, it is still a finite number. Can you at least use them as a black box without bothering about the internals? NOPE. You also have to learn a lot of concepts to even understand the help and error messages for these commands - the worktree, the index, the stash, HEAD, ours vs theirs, conflicts, remotes, tracking branches.
Besides, so many commands come with their own gotchas (git checkout will happily overwrite your local changes - without any warning). Some have bad defaults, so you need to figure out which of the hundreds of options that command supports to make it do what you actually want (e.g. git log --oneline and git diff -w -b). Still others have overloaded semantics and do two completely different things (git checkout switches branches but also restores files).
I find it interesting how many tutorials praise the simplicity of git while simultaneously assume nothing goes ever wrong. It's when you have to pull the main branch into the feature branch you're working on (because you sure don't want to do the big merge in a few weeks when you're done, not the least, because you don't even know whether you're still there to do it), but aren't ready to commit all changes made yet, when Murphy assures that there are conflicts. Then you have to do the stash/pop dance and since you manage to not fix all conflicts, the stash wasn't dropped, which you do manually and you just lost some changes. Then you wished you'd done a back-up before the pull ...
Sure, if you always commit your changes before pulling, then you won't need the stash and (even old CVS documentation reminded us that a VCS tool cannot replace communication) if there are no unrelated changes in the files you're working on, there won't be conflicts, but that just aren't realistic assumptions.
Sounds like you should commit more often inside you topic branches.
In case you are talking about merge conflicts: That's the nature of distributed development other people might trump on places you are currently working on.
I guess there are more intelligent merge strategies. But GIT gives you a list of files that need a manual merge and you have to look into them one by one. GIT even tells you what to do in this case.
I think the idiosyncratic command names are rooted in the fact that git is designed as a peer to peer distributed system as opposed to how it is generally used right now, the server/client workflow. Github even follows and adds to this tradition with the always weird sounding "pull request", since the pull request is normally a mail to a mailgroup with the description of the changes and an actual request to pull that person's changes to the maintainers local repositories.
I'm not sure what is currently being done at developing git, but adapting/creating some porcelain commands accommodating a more centralized workflow even mainly on a semantic level could help with the UX friction.
Also, the obligatory joke "git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space"
> Also, the obligatory joke "git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space"
The scary thing about that one is that I still don't know whether it's just a joke, or if it's the "it's funny because it's true" kind of joke.
The sheer functionality of git is amazing. The number of times I have encountered a new situation and used a previously unknown (to me) feature, or (equally as impressive) been able to harness the flexibility of the software to wrangle some strange edge case are innumerable. All that while also being lightning fast.
Despite having 14 years of experience with Git, I still can't use it without Stackoverflow for any non-daily task. And I've read the internals back in 2008 and understand this, but it doesn't make it any clear how merges, conflict resolution, or amendments to commits work. Absolutely confusing. In Mecrurial a lot more stuff is clear and easy to remember.
Example: I tried rebasing or merging, and got merge conflicts. Started resolving them, git-added some of files, but got stuck, and want to get back to the last commit. git-reset doesn't work. How do I get there? No idea. How does the knowledge of commit hashes, branches and staging area help me? It doesn't.
When conflicts occur when performing rebase, git prints out the following:
```
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
```
The options on how to proceed seem pretty clear to me.
This is just one of a dozen unclear cases, that arise sometimes in git workflow. I do recall the first sentence in the hint, and I could have read the end too, but it's not clear, why it's "rebase --abort", not "reset --hard", that's why it's easy to forget this and other commands.
Also, "git add/rm" is confusing, because they're not opposite of each other -- 'add' puts the file to the stage area, but rm removes it and makes forget.
This is why so many people dislike git. It's a base tool that should have an obvious workflow and very few pitfalls. Instead it allows one to do just about anything at anytime without giving much of a fuck about any resulting mess. All blade, no handle. It's a tool for Linus, by Linus. The average corporate coder is not Linus and doesn't have Linus problems. People don't want a Merkle tree manager, they want a workflow.
Aside from the terrible UI that several other people have mentioned, there are some other things that Git does badly (though I don't know if Mercurial does better):
* Large projects. It has poor monorepo support (especially on Linux), and also poor multirepos support (submodules are really buggy).
* Large files. LFS is a PoC-level hack; not a proper solution.
* Conflict resolution. The default diff algorithm is very dumb, and even with `zdiff3` it doesn't quite give you enough information to easily resolve all conflicts.
Git is very good with large repos, but the monorepo concept doesn't fit the git model. Monorepo is a bad idea with the current DVCS-es unless you use custom tooling. My guess is that people adopt monorepos because they aspire to be Google-scale, but it usually doesn't make sense for their workflow.
If you want monorepo, use Perforce or SVN, but good luck with the speed ;)
Not really. It only very recently got support for partial clones, sparse checkouts (still experimental!) `git status` daemon (only on Windows and Mac!), etc. And that's only because Microsoft is pushing it.
> My guess is that people adopt monorepos because they aspire to be Google-scale, but it usually doesn't make sense for their workflow.
Rubbish, it's nothing to do with wanting to be Google-scale. In fact being Google-scale makes a monorepo more difficult and require custom tooling.
The reason people like monorepos is because they don't have the downsides of multirepos:
* Cross-repo changes are very difficult to do and even harder to test.
* Testing code becomes very difficult. For example if you update a library that's in one repo, how do you test all the things that depend on it? Very difficult with multirepos, trivial with monorepos.
* Git's support for submodules is really bad.
The downside of monorepos is that they are big and slow, but they work fine as long as you aren't Google scale.
> Not really. It only very recently got support for partial clones, sparse checkouts (still experimental!) `git status` daemon (only on Windows and Mac!), etc. And that's only because Microsoft is pushing it.
Which only proves my comment that git is not designed for bigcorp view of monorepos. Kernel is monorepo and works fine.
> The reason people like monorepos is because they don't have the downsides of multirepos:
The reason people like monorepos is that they are lazy to properly organize development process. If you update library in one repo but test it in another, I'd say you need to reconsider your pipeline. But, to each their own.
> Which only proves my comment that git is not designed for bigcorp view of monorepos. Kernel is monorepo and works fine.
Not really; it just means you misunderstood what I meant by "large projects". The Linux kernel is not nearly as large as most company codebases.
> The reason people like monorepos is that they are lazy to properly organize development process. If you update library in one repo but test it in another, I'd say you need to reconsider your pipeline.
Sounds like you just don't have any experience of this sort of thing so don't appreciate the problems. You update the library in one repo and test it in another because that other repo is using the library. You want to make sure your library update doesn't break it.
If you don't test all of the dependants of your library then you're massively increasing the risk of breakage (plus all the other downsides) just so you can use separate repos. That isn't worth it.
I definitely feel the large file support in Mercurial is less bolted-on.
My personal favourite mercurial gui features that I hope make it into git or a mercurial using a git data store are:
phases
revsets (query language for revisions, they also have filesets for the files)
hg grep --diff
hg fa --deleted
hg absorb
I could go into some detail here why Git is the harder to use system of the two, but I think that would miss the bigger point.
IMO, the larger and longer-term problem is that (open source) version control systems seem to be mostly stuck in the early aughts. This may sound provocative, but in principle, Git and Mercurial don't offer much that wasn't already part of Monotone. Meta/Facebook has really been the only actor I am aware of who has been really pushing the envelope in terms of making open source version control more convenient.
If you think I'm being needlessly provocative, just consider this simple example: why don't version control systems (especially ones that can change history) have undo/redo functionality out of the box? I've only seen this as a Facebook extension for Mercurial that never made it into the Mercurial proper (and survived only as part of Sapling).
This is an essential feature of every basic editor nowadays and it is not easy to implement for a VCS, but it's still mind-boggling that after nearly two decades, it isn't considered core functionality of a VCS. Recovering from mistakes remains a pain point in pretty much any VCS, but shouldn't be.
Commit graph visualization is another problem that's just not handled very well by either Git or Mercurial and hasn't really improved much since their early incarnations, if at all. "git log --graph" or "hg log -G" don't really produce output fit for human consumption if you have even a moderately complex branch structure.
Version control systems are still generally very low-level, giving you a lot of primitives and very few high-level operations that aim at making complex workflows less complex.
I've heard this point of view many times, but cannot find an extensive explanation of it. Could anyone elaborate on the issue with the GitHub review UI/UX?
> I hate the GitHub review UI with a passion. At least, right now, GitHub PRs are not a viable option for Mozilla [...] the more general shortcomings in the review UI.
I've found that Graphite [0] has solved this issue for me. It's makes the experience of shipping stacked diffs about the same as the CR tool within AWS
Either way, I hope you like it! I've tried many other tools that aim to implement stacked diffs for GitHub PRs, and Graphite is _by far_ the best. They have their own Web UI but I skip that completely and just use their CLI + GH's UI.
I watched their product overview video last night, but like, I don't grok what the difference between rebasing a branch and rebasing a stack is, and they said something like "if there are conflicts, this is when you'd fix them." but I thought the point was reducing conflicts. It sounds to me like short lived feature branches with a lot of extra terminology.
I really think I just need to actually try the tooling and then examine the git repo. I am very bottom-up brained when it comes to git, and so I need to visualize what commands actually do to the DAG to really grok what's going on.
What are these people talking about? What's the difference between "stacked diffs" and just adding commits to a branch? Who cares if the branch is called "master" or not? You could also force push updated commits (e.g. after fixup and rebase etc) and tools like Gitlab and GitHub can show you the diff between versions (or "changesets", as they call them). Gitlab at least makes it pretty clear when a change has been made and the order things were done in. Pretty sure GitHub does too.
From the second article, a minor point but possibly helpful to other here, he contrasts doing everything in the terminal with stacked commits vs going to the Github UI. If people aren't aware, Github offers a cli tool[1]. I've been using it for a few months now and am finding it does make me more productive -- it's nice to be able to open up a PR directly from my terminal. I do still use the GH UI for a lot of things, but I'll often at least start in the terminal, and it also makes the transition from terminal to browser easy as many commands support the `--web` flag open up the right page for you (eg `gh repo view --web`).
The CLI doesn't help with stacked commits, though. There's tools like spr[1] but none of them are anywhere as pleasant to use as Gerrit (or Phabricator, I guess).
It doesn't -- hence my noting the GH cli as a minor point. It's a tool I've personally found helped increase my productivity, so just wanted to share as others may find it useful too.
I once worked with a guy who hated Python. He also hated IntelliJ and did all of his programming in Eclipse. He hated MacOS and would only run old versions of Windows of Linux.
What I found was that he was just sensitive to change. It took him awhile to get comfortable with something but as soon as he did he would from then on resist any change. Anything that was different to what he was used to he hated.
In some sense, it makes sense. People should prefer processes over tools in many cases. If you have a process that works with one tool but doesn't work with a new tool then you might be better off sticking with the original tool. Broken processes can debilitate organizations.
When people say "I hate X" often what they are really saying is "I have a process to do Y that works for me but tool X makes that process too difficult". The problem is they just say "I hate X" so you never really hear about the process Y which provides the context.
Mine too. I suspect it's the classic explore/exploit dilemma. We've learned enough that every new hotness just doesn't seem that novel or worth the effort to learn given we already see a path to our goals using what we already know.
GitHub PRs are both bad process (no stacking or per-commit review, incentivizes large changes, ...) and bad tool (no inter-diffs, noisy diffs, comments disappear through rebases, slow, ...).
One point: if you are re-reviewing, other platforms (e.g. Phabricator, Gerrit) have much more developed ways to compare changes relative to one another.
Phabricator was awful. It loaded commit messages with irrelevant boilerplate and allowed people to post patches that you couldn’t build for testing because they were just diffs and not actual branches in the repo. Not sad to see it go.
Bias warning: I created CodeApprove to give GitHub reviews a better UI.
GitHub PR review UI is … fine. But it has very little depth. Unlike an IDE it’s hard to grow into a power user of it. It seems to be optimized for simple reviews with 1-2 rounds of a few comments each.
When you do dozens of code reviews every week you want something more. You want something snappy and dense with keyboard shortcuts. You want something that draws your attention to where it’s needed and something that helps you ensure all your conversations reach resolution.
So there’s a lot of room for improvement and GitHub hasn’t shown much interest in improving this area. So 3p UIs are stepping in (Graphite, CodeApprove, Reviewable, etc)
One issue I was discussing with a colleague just the other day is that you cannot leave a comment on lines that are not "part of the diff" (changed or context), which is sometimes really useful for "see this thing over here".
Actually you can’t comment on lines that haven’t been changed if they’re too far from the changed lines! It’s a weird limitation of GitHubs data model.
(source: that’s one of the features that people like most about the review tool I created, CodeApprove)
Annotations can be added by "checks" anywhere, though, I believe.
I like to use that to surface cross-references (annotating anchors whose references appear in changed or context lines, and references whose anchors do).
As the other commenter pointed out, only if they're close enough to a changed line. That's what I meant by "context" (borrowing terminology from diff, where you change the amount of it with -C).
Most of the projects that dislike GitHub's review UI want the functional equivalent of `git range-diff`. Code review systems like Phabricator and Gerrit basically revolve around this as basis of thinking about diffs, their evolution, and how code review progresses.
You want to write 3 patches to a project, that are committed in series, based off of `X`
A ---> B ---> C
X---/
Let's say A cleans up some code, getting it ready for B; it is not mandatory but was just naturally done as part of the change; maybe it's 50 lines. B then adds 500 lines of new code to be reviewed. Finally, C integrates the new code from B; maybe you migrate something to use it, changing a few internal API calls. So C might be a diff of only 5 or 10 lines.
The code reviewer will want to start by reading A, and leaving comments on A. And so on for B, and so on for C. Let's say they leave code review comments on each commit. So now you have a set of things to do.
GitHub encourages you to add a new set of patches on top of the previous 3, so you might publish add commits on top:
A ---> B ---> C --- > D ---> E ---> ...
X---/
Where each change after C incrementally addresses review comments.
In contrast, tools like Gerrit and Phabricator say instead that you should publish new versions of A, B, and C, wholesale. So now we have a new series of 3 patches:
A' ---> B' ---> C'
X---/
This branch might exist in parallel to your old one. So your full commit graph might look like this, now:
A ---> B ---> C
/
/-A' ---> B' ---> C'
X---/
So there's the original series of changes A,B,C, and the new series of changes that respond to all the comments. Think of that as "version 1" of the series and then "version 2"
Now here's the question: how does the code reviewer know that you addressed their comments? Answer: they need to do a range diff between the original version 1 series and the version 2 series:
A ---> B ---> C
| | |
d(A,A') d(B,B') d(C,C')
| | |
A' ---> B' ---> C'
Where d(x,y) = diff(x,y). You're looking at the diff between the two versions of one patch. So instead you view the changes between version 1 of A, and version 2 of A. And so on and so forth for all 3 patches.
This is very useful for example because B might be 500 lines, but responding to review comments may only take 50 lines of fixes. It would be very annoying to re-read the entire 500 line patch, as opposed to just the 50 line incremental patch. This has very big effects as the review cycle goes forth.
People mostly like this review style because it keeps needless "fix review comment" commits out of the history and it "localizes" the unit of code review to each individual patch rather than the whole aggregate. Note that the final version of the series A,B,C will just contain those 3 logical changes, not 3 logical changes + 1 dozen fixup changes.
This not only makes changes more "dense", it improves the ability to navigate the history, and do things like `git blame`; and it means you don't commit things like "fix failing test" which would break bisection.
Note that most of the systems that implement the above review style do not literally use `git range-diff` in their implementation; rather, git range-diff is simply an implementation of this idea that you should review each version of a patch as a diff from the previous version. The tools themselves have their own lifecycle, patch management, APIs, etc that are wholly different from Git's.
Finally, there are lots of things GitHub's UX is just slacking on, functionality aside. You can't comment "anywhere" in a code review, just on changed lines. An annoying one I hate is that you can batch review comments but not batch review resolutions; if you leave 5 comments on a diff, you submit them as a batch. But if you resolve 5 comments, you do it one at a time, which is annoying and easy to lose track of. The UX has too many tabs you have to swap between, which is pointless when you could just make the page a little longer and things like Ctrl+F would work better. And so on, and so forth.
Yes, this, but you've made a very long and amazing and intricate description of something that basically amounts to an essential workflow thing that those of us who worked at e.g. Google or on Chromium just found intuitive and normal: the comments I make are on the specific code/diff at the point in time that the comment was made and when I see you've resolved or updated it, I as a reviewer can see exactly what changed.
GitHub's PR tool sucks for this. It's also clunky, wastes boatloads of screen real estate, and lacks keyboard shortcuts.
These days I work in GitLab's MR system, and it's meh, but slightly better. But I still miss Gerritt. So much better, even if takes a while to get used to.
Yes, it's long-winded, and unfortunately, it's really hard to get across with the above description that the workflow described therein actually is quite simple with the correct tools, and (at least in my opinion) also results in a technically superior outcome. Everything I described above is very intuitive and easy once you get into the groove with something like Phab or Gerrit.
Unfortunately, I think it's sort of lost on people today, because basically everyone is so stubborn about GitHub and you basically have to drag them kicking and screaming to most other tools, even if they have clearly superior UX, much less fundamental design. I used to run an open-source project and we used Phabricator and most of the regular contributors ended up liking it, but the initial hurdle for people was often like pulling teeth (and it felt like people who didn't contribute because of it never missed an opportunity to tell you so, though that may just be sour grapes on my part from hearing it so often.)
Absolutely GitHub is so mediocre. It's fine for most open source project workflows, but when I worked for a company that used it as their main tool I was blown away how badly it managed professional-level code reviews.
Gerrit isn't beautiful, and it also had a lot of knobs that could be tweaked in weird ways. But I do miss aspects of it.
I have been wanting to check out JetBrain's code review tool and see how it looks.
This is an incredible workflow as someone who has only ever used git and GitHub (and poorly at that).
I presume there isn’t really any way to have this kind of workflow using git and GitHub? I’d be interested in something like this at my company but we’re sorta locked in to GitHub already.
There are third party tools like Graphite, CodeApprove, and Reviewable that will basically add these workflows on top of the existing GitHub API.
There's a much more detailed and complex answer to this question (TL;DR you can kind of fake it in various weird ways without too much effort) but that's probably the best approach if you're willing to fork over some money. Graphite in particular seems pretty well reviewed.
You may also want to look into Sapling and tools like git-branchless, which will change your workflow to better accommodate this kind of thinking.
Github review is good for either zero or one round of comments. After that you can't tell what the hell is going on. It has clearly been written by people who do not themselves practice code review. Compare and contrast with Gerrit, which remains usable after many rounds of comments, in both directions, and changes. Compare also Phabricator.
Not bad if you have a junior that knows they are a junior, bad otherwise.
My pet peeve with bitbucket was that when doing code review, you couldn't send all comments and overall review in a batch, every single comment was received in real time by the author. Sometimes I would be still reviewing code when the author pushed fixes to comments I've made before and that still might need other changes. After 15 years they improved that 2 weeks ago. I'm glad it's better, but I hate it with a burning passion.
Bitbucket is much better IME. It has a better handle on the current state of the review rather than offering you the whole diff to re-review whenever someone rebases, and it loses comments much less than github (indeed not at all, in my experience).
As someone who was using darcs in that era: it wasn't just slow in the sense of "it takes 10 seconds rather than 1". It was possible to get into situations where it would take hours to merge changes.
Apart from that it was the best developer experience I've had with a VCS.
I hate to see more and more people switching from Mercurial to Git. The way to overcome the "network effects" is exactly for large projects like Mozilla to stand tall and say clearly that they are going to use Mercurial because it is better and git is worse.
Of course, I shouldn't really expect such from Mozilla given all the other dubious actions they've taken over time.
Git won a long long time ago. Most people’s first VCS is now git. Mercurial is a lot better than SVN so it was able to pick up users back when SVN was dominant, but it’s not really better or worse than git it’s just down to taste. When you consider the network effects and switching costs it’s hard to convince anyone that mercurial is worth learning.
I initially picked up Git because that was the cool/recommended thing to do. Then I started contributing to Firefox and at that time the story for using Git with Firefox's Mercurial repository was much more cumbersome, so I gave up and started using Mercurial instead. Over time, Mercurial has grown on me and these days I actually prefer it over Git.
You'd need some arguments for the assertion that mercurial is better. I think Mozilla is switching because of years of failing to come up with good arguments. And it looks like they gave it a lot of thought. That and an increasing dependence on git internally to the point where people were spending non trivial amounts of time engineering around mercurial and coming up with all sorts of hacks to enable git usage. At least, that's what the article suggests actually happened.
You'll never get consensus on X being better than Y in the tech world. There are always going to be people that insist Y is better than X. And more power to them. But you have to be realistic. There is a lot of stuff that just never gets a lot of traction. Mercurial is one of those things. It's like betamax vs. vhs.
Initially it looked promising and then Github happened and the rest is history. The whole industry now runs on Git and Mercurial sort of flat lined in terms of growth after Github started hosting essentially the entirety of the OSS world (with few but notable exceptions of course). At this point it's a hard sell for new projects and some of the larger remaining users are switching away or are considering it.
I liked bzr because it had simple to understand “versions” I could abuse to use like a single source of truth. Git requires manually applying tags to imitate it.
Because you never wrote it. The curse of open source.
By the time github came about, git already had a lot more mindshare than hg. While hg wasn't yet clearly an also ran, it was clearly the less popular solution, and many open source tools started supporting git but either not supporting hg, or if they did it was an afterthought and often the maintainers broke something hg without noticing and then releasing with broken hg support.
yep, that's what i used to use, but it was shut down and i don't really know why - would it have cost so much to have kept it open? dunno - i really know nothing about the economics of keeping such things going.
I don't recall if this was before or after Atlassian bought Bitbucket, but they had a number of issues keeping the site running. There where so many outages, the site was frequently slow to the point of being useless. I know because we where a paying customer. I suspect that they had to few paying customers and because the service was so prone to outages they had acquired a bad reputation so they couldn't attract new customers. Maybe if Bitbucket had been a Silicon Valley company they would have had access to funding, allowing them to grow in the same way Github did.
When it worked it was fine, but in the end you just got way better service and performance on Github.
The current iteration of Bitbucket isn't even Bitbucket, it's Stash. That works really well to, if you like Atlassian tools.
Didn't Sun have Gatekeepers carefully controlling what commits were made to any given gate, thereby ensuring that the actual source control would never be the limiting factor in scaling things out? (Don't get me wrong, I love mercurial, I just don't think this particular example demonstrates much because it always sounded like they'd sidestepped the issue.)
Yes, any putback to ON required an advocate to vouch for your change. Basically a neck to wring when things go wrong. You generally had me chance so don’t F. Up.
A bit off-topic, but: I am somewhat confused by the claim “Subversion was created by Jim Blandy”. I was around back then, and the names I think of when it comes to “who created Subversion” are Ken Fogel, Ben Collins-Sussman, and Mike Pilato. And certainly many other people, including Jim Blandy. My recollection seems to be supported by e.g. https://news.apache.org/foundation/entry/the-apache-software... and also by looking at the early subversion repository history and mailing list posts.
But I was only a bystander (and early adopter), so maybe something went on "behind the scenes" that warrants this attribution? Or maybe it is a just a bit careless and was meant to be more like "... he was one of the creators", which one probably could justify.
Coincidentally, I just checked the Wikipedia page for Subversion and was surprised that there is basically nothing on the history of Subversion and who created it, which I find sad.
Switching to Git makes sense, but choosing GitHub is diametrically opposed to what Mozilla claim their principles are — specifically principle 6 of the Mozilla Manifesto: “The effectiveness of the internet as a public resource depends upon interoperability (protocols, data formats, content), innovation and decentralised participation worldwide.”
In future it won't be possible to contribute to Firefox without a Microsoft account. If Microsoft decide to close your account (which they're entitled to do — they own the website), you can't participate.
Mozilla were one of the few hold-outs against this particular attempted monopoly. Again, Mozilla makes a short-termist decision that makes sense for a Silicon Valley lifestyle brand, but makes no sense for an independent mission-driven public-service community project.
All I needed to come to this conclusion was the abandonment of interesting (and necessary) projects like Servo, and the continual increase of superiors' salaries.
If I understand correctly, they're moving development to GitHub, and not hosting their own git servers. So you'd need a GitHub (Microsoft) account to merge a change to the code.
parts of the community, if I recall correctly, and to be clear to everyone else since I'm sure you know this:
1. linus didn't use version control at all, he just got patches emailed to him, then every now and then he'd publish a tarball and incremental patches (e.g. a 2.4.11-rc2 patch on top of 2.4.11-rc1) - the world had no visibility into his tree's development aside from the tarballs and inter-version patches he sent out
2. and because of that, no one else used version control for submitting changes, they just sent patches to lkml
3. there was some use of CVS for some ports / subsystems, but again, it was used to generate patches to email to linus
4. people built lots of tools around this work flow, like `patchwork` and horrible shell scripts
Yeah, my understanding is that it's pretty universally Perforce in game dev. For them it's the large file versioning. I work at an ASIC firm and we similarly use Perforce; to some extent for the large file versioning, and to some extent for other general scale benefits.
I've only used SVN and Git and I'm almost 20 years into my career at this point so I know nothing of these others but my game dev friends all use Perforce. I couldn't tell you a single thing about it though.
I kind of like Fossil nowadays, although I'm not entirely on par with their philosophy of not squashing branches. But the "all-in-one" aspect, together with "one binary" is pretty nice.
Software unmaintained kills itself. I wouldn't feel all too bad if you found a different solution that fits your demand. To say one shoe fits all is silly.
I think the short version is: they made `git-cinnabar`, which is a git-to-hg translator, to help git users interact with the Mozilla repos.
----
One contribution I can make:
> For reasons I don't know, Mozilla decided to use separate Mercurial repositories as "branches".
Originally, separate clones was the recommended way to do "topic branches" in Mercurial (not to be confused with "named branches"). There was no direct equivalent to git's branches. Eventually, Mercurial got 'bookmarks' which basically closes that gap, but that only became a core feature in 2011, well after these Mozilla repos were established.
----
Aside: I prefer Mercurial myself, and I hope to keep using it for personal projects until I die (: