[Python-checkins] devguide: Issue #22992: A git developer's guide to hg.

brett.cannon python-checkins at python.org
Fri Jan 16 18:59:40 CET 2015


https://hg.python.org/devguide/rev/51c89a0c30b4
changeset:   726:51c89a0c30b4
user:        Brett Cannon <brett at python.org>
date:        Fri Jan 16 12:59:22 2015 -0500
summary:
  Issue #22992: A git developer's guide to hg.

Thanks to Demian Brecht for the guide!

files:
  gitdevs.rst |  509 ++++++++++++++++++++++++++++++++++++++++
  index.rst   |    3 +
  2 files changed, 512 insertions(+), 0 deletions(-)


diff --git a/gitdevs.rst b/gitdevs.rst
new file mode 100644
--- /dev/null
+++ b/gitdevs.rst
@@ -0,0 +1,509 @@
+:tocdepth: 4
+
+.. highlight:: bash
+.. _gitdevs:
+
+Mercurial for git developers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. contents::
+   :local:
+
+
+Overview
+========
+
+This guide is geared towards prospective contributors who are accustomed to
+git-based development. The intention of this guide is to lower the initial
+barrier of entry for prospective contributors in learning a new source control
+tool. While there are projects that focus on automating this to allow seamless
+bridges between the two systems, this guide focusses solely on native Mercurial
+functionality. As with most tools, this is not the only method of achieving
+git-like workflows with Mercurial. It is intended solely to provide one
+potential path.
+
+Note that this geared towards prospective contributors and the patch workflow.
+Core developers will have a similar workflow, but it will differ in the later
+stages (merge vs patch generation).
+
+The workflow that will be used as the case study for this guide is as follows:
+
+* Clone CPython
+* Find/Create issue in the issue tracker (issueA)
+
+  - Work on issue
+  - Submit patch for review
+
+* Work on another issue (issueB)
+
+  - Work on issue
+  - Commit work in progress
+
+* Address review comments (issueA)
+
+  - Commit work
+  - Submit patch for review
+
+* Continue feature work (issueB)
+* *Rinse and repeat*
+
+
+Git workflow
+============
+
+With the above workflow in mind, simplified steps using git may look like
+this::
+
+    git clone git at github.com:python/cpython.git
+
+    # work on issueA
+    git checkout -b issueA
+    git commit -a
+
+    # start working on issueB
+    git checkout master
+    git checkout -b issueB
+    git commit -a
+
+    # address review comments
+    git checkout issueA
+    git commit -a
+
+    # optionally rebase work
+    git pull --rebase
+
+    # generate patch for submission
+    git diff master..issueA > issueA.patch
+
+    # continue working on issueB
+    git checkout issueB
+
+
+This flow will be used as the base for comparison against Mercurial usage that
+aims to achieve a similar, if not identical, workflow.
+
+
+Main differences between git and hg
+===================================
+
+This section aims to list major differences that may be unexpected by a git
+developer. While there are many differences between git and Mercurial, only
+those that are immediately relevant to new users coming from git are examined.
+
+
+Mercurial branches are global and permanent
+-------------------------------------------
+
+This means that if you create a named branch, it is intended to be long-lived:
+
+    Mercurial branch names may be used for whatever reasons users want.
+    However, a good rule of thumb is to use branch names sparingly and for
+    rather longer lived concepts like "release branches" (rel-1, rel-2, etc)
+    and rather not for short lived work of single developers.
+
+    -- http://mercurial.selenic.com/wiki/Branch#Named_branches
+
+
+If you routinely create short-lived branches for development work and then
+delete them after they've been merged to master, this is something to be aware
+of. You *can* still only push select branches to remotes, so it's not a
+functional issue as far as the public repo goes.
+
+
+Workflow options using Mercurial
+--------------------------------
+
+There are a number of paths that could be taken to achieve a sane development
+workflow. Some of these are:
+
+
+Named branches
+''''''''''''''
+
+    Mercurial supports giving names to branches, by using the branch name
+    property of the changeset (see NamedBranches_). If no branch name was set,
+    Mercurial assigns the branch name "default". So the name of the default
+    branch in a repository is "default" (which, for example, is not displayed
+    when doing a hg log).
+
+    Unfortunately, as Mercurial named (and default) branches are global and
+    permanent, they don't lend themselves well to local development workflows.
+
+
+Queues
+''''''
+
+    The patch queue extension integrates quilt functionality into Mercurial.
+    Changes are maintained as patches which are committed into Mercurial.
+    Commits can be removed or reordered, and the underlying patch can be
+    refreshed based on changes made in the working directory. The patch
+    directory can also be placed under revision control, so you can have a
+    separate history of changes made to your patches.
+
+    While the mq extension can indeed achieve similar functionality, it's quite
+    a different workflow than git and may be difficult to adapt to for those
+    coming from git.
+
+
+Bookmarks
+'''''''''
+
+    Bookmarks can be used as an alternative to NamedBranches_ for tracking
+    multiple lines of development. Systems like Mercurial, CVS, and Subversion
+    store their branch information as a permanent part of each commit. This
+    is useful for future auditing of long-lived branches, as it's always
+    possible to identify which branch a commit was introduced on. Git, by
+    contrast, has "branches" that are not stored in history, which is useful
+    for working with numerous short-lived feature branches, but makes future
+    auditing impossible. Mercurial's bookmark feature is analogous to Git's
+    branching scheme, but can also be used in conjunction with Mercurial's
+    traditional named branches.
+
+    Bookmarks are the feature that emulate git workflows most closely and will
+    therefore be used throughout the remainder of this guide.
+
+
+An introduction to Mercurial bookmarks
+--------------------------------------
+
+While the functionality may seem entirely analogous to git branches
+at first, there are fundamental differences to be aware of:
+
+
+Bookmarks are not git branches
+''''''''''''''''''''''''''''''
+
+Bookmarks are *not* lightweight Git branches. Bookmarks are simply named
+references to commits that are automatically updated when new commits are made.
+This, coupled with the creation of new branch heads when committing from a
+previous commit provides a workflow similar to git branching, but the fact that
+a new branch is *not* created is an important detail to be aware of. This will
+be demonstrated in the `Mercurial workflow`_ section.
+
+
+Bookmarks are local
+'''''''''''''''''''
+
+Mercurial bookmarks are intended for local
+development and can be deleted with ease, whereas branches cannot.
+Note that deleting a bookmark does not mean that the releated changesets
+are also deleted. You must use the `strip extension`_ to do that. Bookmarks can
+be published to a remote repo to be shared, but must explicitly be pushed (see
+http://mercurial.selenic.com/wiki/Bookmarks#Working_with_remote_repositories
+for details).
+
+.. _`strip extension`: http://mercurial.selenic.com/wiki/StripExtension
+
+
+
+Mercurial workflow
+==================
+
+The following details hg usage with the above git workflow in mind. The
+changeset graphs are displayed using :code:`hg log -G -l [num_commits]`,
+which can be tremendously useful when first starting to use hg in order
+to help you understand through visuals what it is that hg does with the
+branches.
+
+
+Cloning
+-------
+
+Pulling the latest CPython code and looking at the current commits::
+
+    hg clone https://hg.python.org/cpython
+
+    @    changeset:   93654:bd97eab25c70
+    |\   tag:         tip
+    | |  parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    | o  changeset:   93653:21257f916668
+    | |  branch:      3.4
+    | |  parent:      93647:737355f61ba2
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:21:12 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    o |  changeset:   93652:70163e18da87
+    | |  user:        Raymond Hettinger <python at rcn.com>
+    | |  date:        Fri Nov 28 14:52:14 2014 -0800
+    | |  summary:     Minor code cleanup.
+
+*Note that in the above graph, `@` represents your current changeset*
+
+
+Working on issueA
+-----------------
+
+Assuming you've found a bug logged against default tip (master head in git-speak),
+create a bookmark, which automatically activates it::
+
+    hg bookmark issueA
+
+Now, the history graph should look like this::
+
+    @    changeset:   93654:bd97eab25c70
+    |\   bookmark:    issueA
+    | |  tag:         tip
+    | |  parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    | o  changeset:   93653:21257f916668
+    | |  branch:      3.4
+    | |  parent:      93647:737355f61ba2
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:21:12 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    o |  changeset:   93652:70163e18da87
+    | |  user:        Raymond Hettinger <python at rcn.com>
+    | |  date:        Fri Nov 28 14:52:14 2014 -0800
+    | |  summary:     Minor code cleanup.
+
+Notice that the only difference between this and the previous one is that
+changeset 91935 now also has the bookmark "issueA". Bookmarks are advanced
+automatically with each subsequent commit.
+
+Once work has been completed on issueA, commit and prepare a patch for
+submission to the issue tracker. Note that Mercurial doesn't have git's concept
+of staging, so all changes will be committed::
+
+    hg commit -m 'fix for issueA'
+
+    @  changeset:   93655:a542bc2066d1
+    |  bookmark:    issueA
+    |  tag:         tip
+    |  user:        Demian Brecht <demianbrecht at example.com>
+    |  date:        Thu Dec 04 17:33:42 2014 -0800
+    |  summary:     issueA
+    |
+    o    changeset:   93654:bd97eab25c70
+    |\   parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    o |  changeset:   93653:21257f916668
+    | |  branch:      3.4
+    | |  parent:      93647:737355f61ba2
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:21:12 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+
+Notice that the new commit's parent was the previous default tip and the
+bookmark has automatically been advanced to the new tip. A patch for submission
+to the issue tracker can now be prepared with::
+
+    hg diff -c 93655 > issueA.patch
+
+The above will diff revision 93655 against its parent. This will work
+regardless of the commit that you happen to currently updated to.
+
+
+Working on issueB
+-----------------
+
+Now that the patch has been submitted and it's pending review, work on another
+issue can be started. Because of how bookmarks work (and as can be seen in the
+previous history graph), the named branch "default" is advanced (remember that
+bookmarks are not git branches). A new named branch (such as in git) has not
+been created. This means that in order to update the working copy back to the
+latest public commit, you must know which commit to revert back to before
+creating a new bookmark::
+
+    hg update 93654
+    hg bookmark issueB
+
+    o  changeset:   93655:a542bc2066d1
+    |  bookmark:    issueA
+    |  tag:         tip
+    |  user:        Demian Brecht <demianbrecht at example.com>
+    |  date:        Thu Dec 04 17:33:42 2014 -0800
+    |  summary:     issueA
+    |
+    @    changeset:   93654:bd97eab25c70
+    |\   bookmark:    issueB
+    | |  parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+    | |
+    o |  changeset:   93653:21257f916668
+    | |  branch:      3.4
+    | |  parent:      93647:737355f61ba2
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:21:12 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+
+
+Addressing issueA review comments
+---------------------------------
+
+While working on my new feature, I've received reviews of my bug fix and want to
+finish that up before continuing on this much longer feature task. First step is
+to commit my current feature work:
+While working on issueB, a review has been completed for issueA. The following
+demonstrates one method of store current state of issueB, and update back to
+issueA::
+
+    hg commit -m 'issueB WIP'
+    created new head
+
+In the above, hg will confirm that a divergent path has been created. This is
+intentional and to be expected::
+
+    hg update issueA
+
+Reviewing the history graph, a new head can now be seen::
+
+    o  changeset:   93656:6c166f6c1970
+    |  bookmark:    issueB
+    |  tag:         tip
+    |  parent:      93654:bd97eab25c70
+    |  user:        Demian Brecht <demianbrecht at example.com>
+    |  date:        Thu Dec 04 17:36:36 2014 -0800
+    |  summary:     issueB WIP
+    |
+    | @  changeset:   93655:a542bc2066d1
+    |/   bookmark:    issueA
+    |    user:        Demian Brecht <demianbrecht at example.com>
+    |    date:        Thu Dec 04 17:33:42 2014 -0800
+    |    summary:     issueA
+    |
+    o    changeset:   93654:bd97eab25c70
+    |\   parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+
+Once review comments have been addressed, commit again and prepare an updated
+patch. In this case, using :code:`hg commit --amend` will amend the previous
+commit with the most recent changes::
+
+    hg commit --amend
+    hg diff -c issueA > issueA.patch
+
+    @  changeset:   93656:bba24fde02f0
+    |  bookmark:    issueA
+    |  tag:         tip
+    |  parent:      93654:bd97eab25c70
+    |  user:        Demian Brecht <demianbrecht at example.com>
+    |  date:        Thu Dec 04 17:33:42 2014 -0800
+    |  summary:     issueA
+    |
+    | o  changeset:   93655:6c166f6c1970
+    |/   bookmark:    issueB
+    |    user:        Demian Brecht <demianbrecht at example.com>
+    |    date:        Thu Dec 04 17:36:36 2014 -0800
+    |    summary:     issueB WIP
+    |
+    o    changeset:   93654:bd97eab25c70
+    |\   parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+
+
+Continue work on issueB
+-----------------------
+
+Work can now be continued on issueB::
+
+    hg update issueB
+
+    o  changeset:   93656:bba24fde02f0
+    |  bookmark:    issueA
+    |  tag:         tip
+    |  parent:      93654:bd97eab25c70
+    |  user:        Demian Brecht <demianbrecht at example.com>
+    |  date:        Thu Dec 04 17:33:42 2014 -0800
+    |  summary:     issueA
+    |
+    | @  changeset:   93655:6c166f6c1970
+    |/   bookmark:    issueB
+    |    user:        Demian Brecht <demianbrecht at example.com>
+    |    date:        Thu Dec 04 17:36:36 2014 -0800
+    |    summary:     issueB WIP
+    |
+    o    changeset:   93654:bd97eab25c70
+    |\   parent:      93652:70163e18da87
+    | |  parent:      93653:21257f916668
+    | |  user:        Ned Deily <nad at example.com>
+    | |  date:        Fri Nov 28 15:22:15 2014 -0800
+    | |  summary:     Issue #16113: Also remove test_case_sha3_224_huge
+
+
+Rebasing your work
+==================
+
+Rebasing was not previously included as it's an optional step.
+
+As patches sometimes take time to have merged, there can be times when you'll
+need to re-apply commits against the latest version in the public repo. Using
+git, you might do this::
+
+   git pull --rebase
+
+The Mercurial equivalent is::
+
+   hg pull --rebase
+
+As this alters history (which Mercurial largely avoids in practice), the rebase
+extension will need to be enabled. To enable the rebase extension, it must be
+added to your .hgrc file::
+
+   [extensions]
+   rebase =
+
+
+Workflow comparison
+===================
+
+Comparing against the git workflow above (skipping optional steps), the hg
+equivalent in its entirety looks like this::
+
+    # git clone git at github.com:python/cpython.git
+    hg clone https://hg.python.org/cpython
+
+    # work on issueA
+    # git checkout -b issueA
+    # git commit -a
+    hg bookmark issueA
+    hg commit
+
+    # start work on issueB
+    # git checkout master
+    hg update [revision_number]
+
+    # git checkout -b issueB
+    # git commit -a
+    hg bookmark issueB
+    hg commit
+
+    # address review comments
+    # git checkout issueA
+    # git commit -a
+    hg update issueA
+    hg commit --amend
+
+    # create patch
+    # git diff master..issueA > issueA.patch
+    hg diff -c issueA > issueA.patch
+
+    # continue working on issueB
+    # git checkout issueB
+    hg update issueB
+
+
+.. _NamedBranches: http://mercurial.selenic.com/wiki/NamedBranches
diff --git a/index.rst b/index.rst
--- a/index.rst
+++ b/index.rst
@@ -49,6 +49,7 @@
 * `Buildbot status`_
 * :doc:`faq`
 * PEPs_ (Python Enhancement Proposals)
+* :doc:`gitdevs`
 
 
 .. _contributing:
@@ -83,6 +84,7 @@
     * :doc:`devcycle`
     * :doc:`buildbots`
     * :doc:`coverity`
+* :doc:`gitdevs`
 
 It is **recommended** that the above documents be read in the order listed.  You
 can stop where you feel comfortable and begin contributing immediately without
@@ -209,6 +211,7 @@
    compiler
    coverity
    clang
+   gitdevs
    faq
 
 

-- 
Repository URL: https://hg.python.org/devguide


More information about the Python-checkins mailing list