4 ms·
Hm, I was hoping there would be higher-level differences than that. Like maybe the notion of having an index and staging area would be fundamentally different (
by mehrdadn 7y ago
Hm, I was hoping there would be higher-level differences than that. Like maybe the notion of having an index and staging area would be fundamentally different (or absent), or the notion of committing locally and pushing remotely would be fundamentally different, or something like that. Which is not to say command names aren't also confusing in git ('git add' to remove a file is my favorite), but they're not really where I imagined the substantial differences would lie?
- deleted 7y ago[deleted]
- jcranmer 7y ago> the notion of having an index and staging area would be fundamentally different (or absent) Mercurial indeed lacks a staging area > the notion of committing locally and pushing remotely would be fundamentally different If you enable phases, it does. By default, all local commits are "draft" commits, which can have history edited. But when you push to (or pull from) a public repository, it becomes a "public" commit, and Mercurial will refuse to edit those commits. There's also a "secret" phase, which Mercurial will refuse to push to a public repository. You can also configure whether or not remote repositories are public or not. The other fun feature is changeset evolution: when you rebase a changeset, Mercurial will keep the original changeset around with a link between the old and new versions of it. If you push the rebase remotely to a repository that previously had the original, Mercurial will tell people that changesets based on the original also need to be rebased when they pull it, and the history information will let them use the regular rebase flow to do it. Too bad BitBucket is dropping hg repos...
- doubleunplussed 7y ago> Mercurial indeed lacks a staging area I'm sure someone will dispute that it is the same as the staging area, but mercurial does have the ability to only include some things in commits, and I use it daily. I admit I have no idea how it works on the command line, but in tortoisehg I can select individual files and hunks thereof to add to a commit (screenshot: https://imgur.com/ErPEjSN https://imgur.com/ErPEjSN). It's my impression that loads of people use this feature and somehow don't notice it exists, and will openly agree that mercurial lacks a staging area. My opinion is that defaulting to including changes from all files previously committed is such a sensible default that it makes the feature so seamless that people forget it exists even whilst using it. Kinda like how people from the US think you can't turn left on red in Australia (equivalent of right on red in the US). You can, but the existence of slip lanes everywhere its allowed mean you don't actually face the red light when doing so. This hides it so effectively that I've seen several people complaining that they can't turn on red, not noticing that they do it every day.
- jcranmer 7y agoMecurial lets you choose which files you want to commit on the command line, either by simply specifying all the relevant globs, or by using -I (include) and -X (exclude) flags to compose a more complex pattern matching. You can also use interactive commit mode to open up a TUI to select which files you want to load. Alternatively, you can also add stuff to the top commit with `hg commit --amend`. git has basically all of these features. What Mercurial doesn't have is a separate repository concept of an incomplete commit that has awkward, and often inconsistent, interactions with several common repository commands. Git has this, and this is the staging area. The UI feature you use has nothing to do with the staging area, and is in fact closer to the `hg commit -i` interactive commit mode.
- DaiPlusPlus 7y agoWhat about committing partial changes to files (like git’s hunks)?
- pseudalopex 7y ago"hg commit -i" does that.
- rkangel 7y agoI seem to remember using the hg record extension.
- doubleunplussed 7y agoYes, hg's interactive commit allows this (and if you look at my screenshot, you can see tortoisehg presents checkboxes next to hunks in the diff, this is the way I use it)
- cannam 7y agoThis makes for one difference which sometimes bites people even if they use the two tools in the same way: if you change a file "while committing it", e.g. changing it in one window while writing the commit message in another, Mercurial will commit the changed version, while Git of course commits the file as it was when you staged it, or when you ran commit -a. I find this quite handy in Mercurial, as I sometimes realise while writing the commit message that e.g. I forgot to remove a line of temporary debug output, and I can still go and do it before I save the commit message. But that's very bad form that reflects badly on me. The way Git does it feels more correct.
- rkangel 7y agoMercurial does have a staging area, it is just turned off by default (and this is a good thing). Mercurial has a very good extension system, and ships several useful extension in the default installation. The 'record' extension adds the 'commit individual hunks' functionality of the git staging area, and needs a one line "record=" in your config file to enable it. See: https://www.mercurial-scm.org/wiki/RecordExtension https://www.mercurial-scm.org/wiki/RecordExtension By having some of these functionalities in extensions, the core interface is kept simpler and easier to learn, but the more powerful features are still there for those who want them.
- throw0101a 7y ago> Mercurial indeed lacks a staging area Perhaps this: * https://www.mercurial-scm.org/wiki/GitConcepts#Git.27s_staging_area https://www.mercurial-scm.org/wiki/GitConcepts#Git.27s_stagi...
- rcthompson 7y agoI don't believe hg has an equivalent of the git index, although there are other ways to get similar functionality if you want it. The repository formats are different, of course, but it's easy enough to convert from one to the other. Git branches are mutable pointers that don't get recorded in the commit history, while in hg each commit records the branch it was committed to. hg has "bookmarks" that work like git's branches; I don't think git has any equivalent of hg-style branches. For the most part, you can do anything with either one that you could do with the other, and the practical differences are mostly just in the UI, as well as a cultural component (e.g. hg more strongly discouraging history rewriting is part UI, part culture). Personally, I prefer the git UI because it has a more direct mapping onto manipulating a DAG of commits, but obviously not everyone feels that way, and I don't expect them to. When I first started with DVCS, I started with hg since it seemed easier to learn. (Although really, my DVCS UI of choice is Magit, which I use for 99.9% of git stuff, to the point where I almost never need to actually run git myself on the command line.)
- MiyamotoAkira 7y ago>> more direct mapping onto manipulating a DAG of commits That would be a leaky abstraction. The fact that is using DAG should be irrelevant. If they find a better way of doing the work, that shouldn't really affect the ux.
- rcthompson 7y agoI'm not sure I follow. A git history is literally a DAG of commits, and if you understand what each command is doing in terms of that DAG, there's very little abstraction at all, so there's nothing to leak.
- throw0101a 7y ago> I don't believe hg has an equivalent of the git index, although there are other ways to get similar functionality if you want it. Queues? * http://stevelosh.com/blog/2010/08/a-git-users-guide-to-mercurial-queues/ http://stevelosh.com/blog/2010/08/a-git-users-guide-to-mercu...
- kadoban 7y agoThe general consensus seems to be that git is an excellent semantic model wrapped in a ... mostly acceptable command-line UI. Even most big git fans aren't going to deny that the UI has some big warts (I'm a fan of git myself, there's _definitely_ things I'd change in a perfect world).
- mehrdadn 7y agoI mostly agree with two exceptions: - [Major] I feel (but could be potentially convinced otherwise?) that there is one very deep fundamental flaw in the semantic model, and that is the fact that the identity of a commit depends on its history. I simply do not understand why this has to be the case. If I later discover a ZIP backup of the tree that I forgot to commit, and I want to insert it into the history, it shouldn't suddenly completely break the entire repo. Of course it seems fine to have a hash that depends on the history, and it's very likely useful for many purposes, but that shouldn't be the primary mechanism for identifying commits. By default, I think the identity of a commit should be defined by a hash of its contents only, but independent of its history. This would (among other things) let you re-write the history structure without rewriting the commits themselves and causing other people to have to reset their repos, which seems insanely useful to me. - [Minor] I wish metadata was also preserved.
- CJefferson 7y agoI used to think that, but life gets complicated. How do you transmit a commit with its history? It used to be you just sent a single hash, now you would have to send all the commits of the whole history. Also how would you merge repositories with different histories? I spend some time thinking about and I couldn't come up with anything sensible which wouldn't lead to history being effectively brokenm
- mehrdadn 7y agoI'm not sure I understand what the problem is. I'm only talking about the logical objects, not the physical representation. You can still store diffs and you can still have history hashes if that helps you with storage, processing, etc. -- that's perfectly fine. The storage optimizations should be independent of the logical structure. I'm just saying the logical identity of a commit shouldn't depend on its history. For example, if someone removes a commit from the history, that shouldn't have to trash anyone's repo and be such a massively destructive operation. It should only cause a client (in the worst case) to resync its history hashes from that point onward the next time it pulls -- which is quite a cheap, fast, and non-intrusive operation. (Say, 100k commits with 20B SHA-1 hashes would just be ~2MB.)