Commits

Friedrich Kastner-Masilko committed 9cd70ba

Added debug command tricks to advanced section.

Comments (0)

Files changed (1)

advanced/2010-04-10-debug-command-tricks.html

+{% extends "_tip.html" %}
+{%hyde
+    title: Debug Command Tricks
+    author_name: Friedrich Kastner-Masilko
+    author_link: http://bitbucket.org/face
+    created: 2010-04-10
+%}
+
+
+{% block excerpt %}
+Mercurial has some "hidden" debug commands that can make your day in special
+situations.
+{% endblock %}
+
+
+{% block tip %}
+
+If you tried 'hg help --debug', you may be familiar with the commands prefixed
+with 'debug'. Most of them are used to inspect Mercurial's internal storage, but
+some can come handy in certain situations. Two of these commands are
+'hg debugsetparents' and 'hg debugrebuildstate'.
+
+The first command forces Mercurial to forget the "real" parent revisions of a
+working-copy in favour of the specified revisions in 'debugsetparents'. The
+second command is forcing Mercurial to rebuild its internal state.
+
+So how can this be useful in normal conditions at all? Here are 3 scenarios
+where it comes handy to work with them:
+
+### 1. Late-binding working-copy with repository.
+
+Imagine an interesting project hosted with Mercurial. At first you only download
+a snapshot of the project to inspect the code and try something out. You didn't
+clone it fully, because you wanted to avoid the overhead to just check the
+source.
+
+Later in the process of playing with the code, you realize that this is going to
+be a longer-lasting relationship, so you decide to clone the repo and commit
+your changes. Since it is quite a big working-copy and you renamed/deleted/added
+some files, you don't want to copy the whole thing over some checkout in order
+to not confuse the working-copy state. So how to commit this state at the proper
+location?
+
+The solution is to copy the .hg folder into the snapshot's root and issue:
+
+    $ hg debugsetparent tip
+    $ hg debugrebuildstate
+    $ hg commit -Am "my snapshot"
+
+### 2. Creating alternate check-ins.
+
+If you are anything like me, you don't trust yourself. Therefore, you'd want to
+add alternative work BEFORE you delete one of the alternatives. So the usual
+workflow of using rollback to take back an ill-composed commit is not your
+thing.
+
+Instead, it is possible to simply:
+
+    $ hg debugsetparent tip^^
+    $ hg debugrebuildstate
+
+And you are back at the state you where before you commited, just with the
+"wrong" commit still there.
+
+### 3. Simulate Git's --no-ff merges with anonymous heads.
+
+Most of the workflows for Git are easily reproducable with Mercurial, but some
+of them ([gitflow]) use so-called "non-fast-forward" merges. These merges can be
+done in Mercurial, too, but only with named-branches:
+
+    $ hg sl
+    $ echo x > x
+    $ hg ci -Am "base"
+    adding x
+    $ hg branch feature
+    marked working directory as branch feature
+    $ echo y > x
+    $ hg ci -m "feature"
+    $ hg up default
+    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+    $ hg merge feature
+    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+    (branch merge, don't forget to commit)
+    $ hg ci -m "merged"
+    $ hg glog
+    @    changeset:   2:e0502e1d12c6
+    |\   tag:         tip
+    | |  parent:      0:387ca709aeaf
+    | |  parent:      1:205ec0dce78f
+    | |  summary:     merged
+    | |
+    | o  changeset:   1:205ec0dce78f
+    |/   branch:      feature
+    |    summary:     feature
+    |
+    o  changeset:   0:387ca709aeaf
+       summary:     base
+
+As you can see in the above graphlog output, the merge contains no actual
+information besides indicating the merging of two named-branches ('default' and
+'feature'). As with Mercurial 1.5.1, you can't do that with anonymous heads:
+
+    $ echo x > x
+    $ hg ci -Am "base"
+    adding x
+    $ echo y > x
+    $ hg ci -m "feature"
+    $ hg up 0
+    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+    $ hg merge 1
+    abort: nothing to merge (use 'hg update' or check 'hg heads')
+
+Why would you want to do that with anonymous heads, anyway? Well, one way of
+simulating Git branches is the bookmark extension. Unfortunately, using
+bookmarks (to name anonymous heads) is still using anonymous heads, so the above
+problem gets in your way:
+
+    $ hg bookmark master
+    $ hg bookmark feature -r 1
+    $ hg bookmark
+     * master                    0:6965ee5bb884
+       feature                   1:2061809a8e23
+    $ hg merge feature
+    abort: nothing to merge (use 'hg update' or check 'hg heads')
+
+The solution:
+
+    $ hg debugsetparents master feature
+    $ hg revert -a -r feature
+    reverting x
+    $ hg ci -m "merged"
+    $ hg glog
+    @    changeset:   2:0dfae55684f6
+    |\   tag:         master
+    | |  tag:         tip
+    | |  parent:      0:6965ee5bb884
+    | |  parent:      1:2061809a8e23
+    | |  summary:     merged
+    | |
+    | o  changeset:   1:2061809a8e23
+    |/   tag:         feature
+    |    summary:     feature
+    |
+    o  changeset:   0:6965ee5bb884
+       summary:     base
+
+[gitflow]: http://nvie.com/git-model
+
+{% endblock %}
+{
+
+
+
+