Size: 7841
Comment:
|
Size: 324
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
#pragma section-numbers 2 = Mercurial for Git users = ---- /!\ '''''UNFINISHED, PLEASE DO NOT LINK YET''''' ---- [http://git-scm.com Git] is a very popular DistributedSCM that works very similarly to Mercurial. However, there are some conceptual differences that may puzzle the casual Git user when using Mercurial. [[TableOfContents]] == Logical architecture == In general, Git's feature set is the largest among all [:DistributedSCM:DistributedSCM] software, but Mercurial can equally cover a great extent of it. === History model === Mercurial's view of history is, just like git's, a [:UnderstandingMercurial:DAG] or Directed Acyclic Graph of commits. The difference is that, in Mercurial, ''commits'' are called ''changesets'', a rough approximation of the ''tree'' git concept is the ''manifest'' and there is no notion of ''blobs'' because Mercurial refers directly to files. Aside from that, the graphical representation of history is the same in both cases. They both use the SHA1 hash to identify commits/changesets. Additionally, Mercurial also provides a '''local''' ascending number for each revision instead of providing the reverse count notation provided by git (for example, HEAD~4). === Branch model === Also like in git, Mercurial supports branching in different ways. First and foremost, each clone of a repository represents a branch; eventually identical to other clones of the same repositories. This way of branching sometimes referred as ''heavy branches'' and it works almost the same in both systems. Then git has its famous ''lightweight branches'', which allow to switch between development lines within the same clone of a repository. Take the following history graph as an example: {{{#!dot digraph { label = "Light branches example"; rankdir = LR; node [shape=box]; a -> b -> c [dir=back]; c -> d -> e [dir=back]; c -> f -> g [dir=back]; e -> X [dir=back, style=dotted]; g -> Y [dir=back, style=dotted]; X [shape=plaintext]; Y [shape=plaintext]; } }}} In git, branches `X` and `Y` are simply references to the `e` and `g` commits. If a new commit is appended to `e` then the reference `X` would then point to such commit, like so: {{{#!dot digraph { label = "Moving reference example"; rankdir = LR; node [shape=box]; a -> b -> c [dir=back]; c -> d -> e -> h [dir=back]; c -> f -> g [dir=back]; h -> X [dir=back, style=dotted]; g -> Y [dir=back, style=dotted]; X [shape=plaintext]; Y [shape=plaintext]; } }}} Mercurial has '''always''' supported these kind of branches, but with a different name and somehow in an anonymous way. In Hg, the `X` and `Y` branches are called ''heads'' and, until recently, they had to be referred by their changeset identifier; either local (number) or global (SHA1 hash). In brief, is like using git detached heads instead of branch names, but much easier (see `hg help heads`). Since Mercurial 1.1, the BookmarksExtension provides a way to identify (and follow) a light branch with a symbolic name, similarly to git. The ''bookmarks'' does not perfectly mimic git branches in the case of two bookmarks pointing to the same head (or two branches referencing the same commit). In git, a commit only updates the working branch while in Mercurial, a changeset updates all the bookmarks pointing to it. (!) BookmarksExtension from Mercurial version 1.2 (to be released) solves this issue and, thus, gets closer in approaching git's lightweight branches. `` <!> Keep in mind that bookmarks do not propagate over clones, pulls nor pushes because they are not part of the history data nor reflected on the WireProtocol. Finally, Mercurial has another branching functionality called NamedBranches, also known as long lived branches. This kind of branches do not have a git equivalent. For more information about named branches: * [:Branch:Branch] * NamedBranches * MultipleHeads === Tag model === Like with branches. Both git and Mercurial support two tag levels: ''local'' and ''global''. Local tags are only visible where they were created and do not propagate, so they behave practically the same in both systems. Global tags are a bit more intriguing. In git, they have a dedicated repository object type; these tags are usually referred as ''annotated tags''. In Mercurial, though, they are stored in a special text file called `.hgtags` residing in the root directory of a repository clone. This design tends to confuse many Hg newcomers because the tagging action (when global) implies a modification of the `.hgtags` file and its commit. Two important things need to be remembered about how `.hgtags` is handled: 1. The file only grows and should not be edited, except when it (rarely) generates a merge conflict. 2. Because it is revision controlled, there is a corresponding [:Revlog:revlog]. When looking for tags, only the latest revision of `.hgtags` is parsed; never mind the checked out copy revision. There is a particularly puzzling scenario when cloning from a repository by tag. Consider the following history graph: {{{#!dot digraph { label = "Global tag example"; rankdir = LR; node [shape=box]; a -> b -> c [dir=back]; c -> T [dir=back, style=dotted]; T [shape=plaintext]; c -> "d: add tag T" -> e -> f [dir=back]; } }}} If you clone a new repository using `hg clone --rev T`, the history graph of the cloned repository would look like this: {{{#!dot digraph { label = "Clone by global tag example"; rankdir = LR; node [shape=box]; a -> b -> c [dir=back]; } }}} Therefore, in the new repository tag `T` does not exist. The reason behind this is because in the original repository tag `T` points to changeset `c`; however, tag `T` is added by commit `d` which is a descendant of `c`. As the clone command limits the history up to changeset `c`, the addition of the tag is not included in the new repository. Things work similarly when tagging a particular revision using `hg tag --rev ...` Regarding tag propagation across repositories, Mercurial has very simple semantics. From the history and WireProtocol point of view, the `.hgtags` file is treated like the rest of the tracked files. It means that any global tagging operation becomes visible to everyone just like any other commit. Of course, with the exception described above. See also: [http://hgbook.red-bean.com/hgbookch8.html#x12-1580008.1 Giving a persistent name to a revision]. == Behavioral differences == In most design decisions, Mercurial tries to avoid exposing excessive complexity to the user. This sometimes can lead to believe both systems have nothing in common when in practice the difference is subtle, and vice versa. === Communication between repositories === TODO === Git's staging area === Git is the only [:DistributedSCM:DistributedSCM] that exposes the concept of ''index'' or ''staging area''. The others may implement and hide it, but in any other case the user is aware nor has to deal with it. MORE TO COME == Command equivalence table == The table presented below is far from being complete due to the large amount of command and switch combinations that git offers. Nevertheless, it tries to cover the most shocking changes when moving from git to Hg: ||<:>'''Git command'''||<:>'''Hg command'''||<:>'''Notes'''|| ||`git pull`||`hg fetch`||Requires the FetchExtension to be enabled.|| ||`git fetch`||`hg pull`|| || ||`git reset --hard`||`hg revert -a --no-backup`|| || ||`git revert `''<commit>''||`hg backout `''<cset>''|| || |
Rey is what folks call him yet he doesn't like whenever folks use his full name. Virgin Islands has always been his house. To fix computers is something he would never give up. Accounting has been his industry for some time. You may constantly discover his website here: http://ankuzic.com/members/zugvirgie/activity/3081/ |
Rey is what folks call him yet he doesn't like whenever folks use his full name. Virgin Islands has always been his house. To fix computers is something he would never give up. Accounting has been his industry for some time. You may constantly discover his website here: http://ankuzic.com/members/zugvirgie/activity/3081/