[Python-checkins] devguide: #14468: document the use of the share extension as the suggested approach for
ezio.melotti
python-checkins at python.org
Tue Feb 26 03:33:34 CET 2013
http://hg.python.org/devguide/rev/a50e537c5914
changeset: 602:a50e537c5914
user: Ezio Melotti <ezio.melotti at gmail.com>
date: Tue Feb 26 04:29:58 2013 +0200
summary:
#14468: document the use of the share extension as the suggested approach for core developers.
files:
committing.rst | 409 +++++++++++++++++-------------------
1 files changed, 191 insertions(+), 218 deletions(-)
diff --git a/committing.rst b/committing.rst
--- a/committing.rst
+++ b/committing.rst
@@ -42,6 +42,61 @@
making a complete patch.
+Handling Others' Code
+---------------------
+
+As a core developer you will occasionally want to commit a patch created by
+someone else. When doing so you will want to make sure of some things.
+
+First, make sure the patch is in a good state. Both :ref:`patch` and
+:ref:`helptriage`
+explain what is to be expected of a patch. Typically patches that get cleared by
+triagers are good to go except maybe lacking ``Misc/ACKS`` and ``Misc/NEWS``
+entries.
+
+Second, make sure the patch does not break backwards-compatibility without a
+good reason. This means :ref:`running the test suite <runtests>` to make sure
+everything still passes. It also means that if semantics do change there must
+be a good reason for the breakage of code the change will cause (and it
+**will** break someone's code). If you are unsure if the breakage is worth it,
+ask on python-dev.
+
+Third, ensure the patch is attributed correctly by adding the contributor's
+name to ``Misc/ACKS`` if they aren't already there (and didn't add themselves
+in their patch) and by mentioning "Patch by <x>" in the ``Misc/NEWS`` entry
+and the checkin message. If the patch has been heavily modified then "Initial
+patch by <x>" is an appropriate alternate wording.
+
+If you omit correct attribution in the initial checkin, then update ``ACKS``
+and ``NEWS`` in a subsequent checkin (don't worry about trying to fix the
+original checkin message in that case).
+
+
+Contributor Licensing Agreements
+--------------------------------
+
+It's unlikely bug fixes will require a `Contributor Licensing Agreement`_
+unless they touch a *lot* of code. For new features, it is preferable to
+ask that the contributor submit a signed CLA to the PSF as the associated
+comments, docstrings and documentation are far more likely to reach a
+copyrightable standard.
+
+For Python sprints we now recommend collecting CLAs as a matter of course, as
+the folks leading the sprints can then handle the task of scanning (or otherwise
+digitising) the forms and passing them on to the PSF secretary. (Yes, we
+realise this process is quite archaic. Yes, we're in the process of fixing
+it. No, it's not fixed yet).
+
+As discussed on the PSF Contribution_ page, it is the CLA itself that gives
+the PSF the necessary relicensing rights to redistribute contributions under
+the Python license stack. This is an additional permission granted above and
+beyond the normal permissions provided by the chosen open source license.
+
+.. _Contribution: http://www.python.org/psf/contrib/
+.. _Contributor Licensing Agreement:
+ http://www.python.org/psf/contrib/contrib-form/
+
+
NEWS Entries
------------
@@ -129,7 +184,7 @@
automatically closed as "fixed".
Working with Mercurial_
------------------------
+=======================
As a core developer, the ability to push changes to the official Python
repositories means you have to be more careful with your workflow:
@@ -201,253 +256,171 @@
.. _eol extension: http://mercurial.selenic.com/wiki/EolExtension
-Handling Others' Code
----------------------
+Clones Setup
+------------
-As a core developer you will occasionally want to commit a patch created by
-someone else. When doing so you will want to make sure of some things.
+There are several possible ways to set up your Mercurial clone(s). If you are
+a core developer, you often need to work on the different branches, so the best
+approach is to have a separate clone/directory for each active branch. If you
+are a contributor, having a single clone might be enough.
-First, make sure the patch is in a good state. Both :ref:`patch` and
-:ref:`helptriage`
-explain what is to be expected of a patch. Typically patches that get cleared by
-triagers are good to go except maybe lacking ``Misc/ACKS`` and ``Misc/NEWS``
-entries.
+Single Clone Approach
+'''''''''''''''''''''
-Second, make sure the patch does not break backwards-compatibility without a
-good reason. This means :ref:`running the test suite <runtests>` to make sure
-everything still passes. It also means that if semantics do change there must
-be a good reason for the breakage of code the change will cause (and it
-**will** break someone's code). If you are unsure if the breakage is worth it,
-ask on python-dev.
+This approach has the advantage of being simpler because it requires a single
+clone/directory, but, on the other hand, it requires you to recompile Python
+every time you need to switch branch. For this reason, this approach is not
+suggested to core developers, but it's usually suitable for contributors.
-Third, ensure the patch is attributed correctly by adding the contributor's
-name to ``Misc/ACKS`` if they aren't already there (and didn't add themselves
-in their patch) and by mentioning "Patch by <x>" in the ``Misc/NEWS`` entry
-and the checkin message. If the patch has been heavily modified then "Initial
-patch by <x>" is an appropriate alternate wording.
+See :ref:`checkout` to find information about cloning and switching branches.
-If you omit correct attribution in the initial checkin, then update ``ACKS``
-and ``NEWS`` in a subsequent checkin (don't worry about trying to fix the
-original checkin message in that case).
+Multiple Clones Approach
+''''''''''''''''''''''''
+This approach requires you to keep a separate clone/directory for each active
+branch, but, on the other hand, it doesn't require you to switch branches and
+recompile Python, so it saves times while merging and testing a patch on the
+different branches. For this reason, this approach is suggested to core
+developers.
-Contributor Licensing Agreements
---------------------------------
+The easiest way to do this is by using the `share extension`_, that can be
+enabled by adding the following lines to your ``~/.hgrc``::
-It's unlikely bug fixes will require a `Contributor Licensing Agreement`_
-unless they touch a *lot* of code. For new features, it is preferable to
-ask that the contributor submit a signed CLA to the PSF as the associated
-comments, docstrings and documentation are far more likely to reach a
-copyrightable standard.
+ [extensions]
+ share =
-For Python sprints we now recommend collecting CLAs as a matter of course, as
-the folks leading the sprints can then handle the task of scanning (or otherwise
-digitising) the forms and passing them on to the PSF secretary. (Yes, we
-realise this process is quite archaic. Yes, we're in the process of fixing
-it. No, it's not fixed yet).
+Once you have :ref:`cloned the hg.python.org/cpython repository <checkout>`
+you can create the other shared clones using::
-As discussed on the PSF Contribution_ page, it is the CLA itself that gives
-the PSF the necessary relicensing rights to redistribute contributions under
-the Python license stack. This is an additional permission granted above and
-beyond the normal permissions provided by the chosen open source license.
+ $ hg share cpython 2.7 # create a new shared clone
+ $ cd 2.7 # enter the directory
+ $ hg up 2.7 # switch to the 2.7 branch
-.. _Contribution: http://www.python.org/psf/contrib/
-.. _Contributor Licensing Agreement:
- http://www.python.org/psf/contrib/contrib-form/
+You can then repeat the same operation for the other active branches.
+This will create different clones/directories that share the same history.
+This means that once you commit or pull new changesets in one of the clones,
+they will be immediately available in all the other clones (note however that
+while you only need to use ``hg pull`` once, you still need to use ``hg up``
+in each clone to update its working copy).
+In order to apply a patch, commit, and merge it on all the branches, you can do
+as follow::
-Forward-Porting
+ $ cd 2.7
+ $ hg pull ssh://hg@hg.python.org/cpython
+ $ hg up
+ $ hg import --no-c http://bugs.python.org/url/to/the/patch.diff
+ $ # review, run tests, run `make patchcheck`
+ $ hg ci -m '#12345: fix some issue.'
+ $ # switch to 3.2 and port the changeset using `hg graft`
+ $ cd ../3.2
+ $ hg up
+ $ hg graft 2.7
+ $ # switch to 3.3, merge, and commit
+ $ cd ../3.3
+ $ hg up
+ $ hg merge 3.2
+ $ hg ci -m '#12345: merge with 3.2.'
+ $ # switch to 3.x, merge, commit, and push everything
+ $ cd ../3.x
+ $ hg up
+ $ hg merge 3.3
+ $ hg ci -m '#12345: merge with 3.3.'
+ $ hg push ssh://hg@hg.python.org/cpython
+
+If you don't want to specify ssh://hg@hg.python.org/cpython every time, you
+should add to the ``.hg/hgrc`` files of the clones::
+
+ [paths]
+ default = ssh://hg@hg.python.org/cpython
+
+Unless noted otherwise, the rest of the page will assume you are using the
+multiple clone approach, and explain in more detail these basic steps.
+
+.. _share extension: http://mercurial.selenic.com/wiki/ShareExtension
+
+
+Active branches
---------------
-If the patch is a bugfix and it does not break
-backwards-compatibility *at all*, then it should be applied to the oldest
-branch applicable and forward-ported until it reaches the in-development branch
-of Python (for example, first in ``3.2``, then in ``3.3`` and finally in
-``default``). A forward-port instead of a back-port is preferred as it allows
-the :abbr:`DAG (directed acyclic graph)` used by hg to work with the movement of
-the patch through the codebase instead of against it.
+If you do ``hg branches`` you will see a list of branches. ``default`` is the
+in-development branch, and is the only branch that receives new features. The
+other branches only receive bug fixes (``2.7``, ``3.2``, ``3.3``), or security
+fixes (``2.6``, ``3.1``). Depending on what you are committing (feature, bug
+fix, or security fix), you should commit to the oldest branch applicable, and
+then forward-port until the in-development branch.
-Note that this policy applies only within a major version - the ``2.7`` branch
-is an independent thread of development, and should *never* be merged to any
-of the ``3.x`` branches or ``default``. If a bug fix applies to both ``2.x``
-and ``3.x``, the two additions are handled as separate commits. It doesn't
-matter which is updated first, but any associated tracker issues should be
-closed only after all affected versions have been modified in the main
-repository.
-.. warning::
- Even when porting an already committed patch, you should **still** check the
+Merging order
+-------------
+
+There are two separate lines of development: one for Python 2 (the ``2.x``
+branches) and one for Python 3 (the ``3.x`` branches and ``default``).
+You should *never* merge between the two major versions (2.x and 3.x) ---
+only between minor versions (e.g. 3.x->3.y). The merge always happens from
+the oldest applicable branch to the newest branch within the same major
+Python version.
+
+
+Merging between different branches (within the same major version)
+------------------------------------------------------------------
+
+Assume that Python 3.4 is the current in-development version of Python and that
+you have a patch that should also be applied to Python 3.3. To properly port
+the patch to both versions of Python, you should first apply the patch to
+Python 3.3::
+
+ cd 3.3
+ hg import --no-commit patch.diff
+ # Compile; run the test suite
+ hg ci -m '#12345: fix some issue.'
+
+Then you can switch to the ``3.x`` clone, merge, run the tests and commit::
+
+ cd ../3.x
+ hg merge 3.3
+ # Fix any conflicts; compile; run the test suite
+ hg ci -m '#12345: merge with 3.3.'
+
+If you are not using the share extension, you will need to use
+``hg pull ../3.3`` before being able to merge.
+
+.. note::
+ Even when porting an already committed patch, you should *still* check the
test suite runs successfully before committing the patch to another branch.
Subtle differences between two branches sometimes make a patch bogus if
ported without any modifications.
-Porting Within a Major Version
-''''''''''''''''''''''''''''''
+Porting changesets between the two major Python versions (2.x and 3.x)
+----------------------------------------------------------------------
-Assume that Python 3.4 is the current in-development version of Python and that
-you have a patch that should also be applied to Python 3.3. To properly port
-the patch to both versions of Python, you should first apply the patch to
-Python 3.3::
+Assume you just committed something on ``2.7``, and want to port it to ``3.2``.
+You can use ``hg graft`` as follow::
- hg update 3.3
- hg import --no-commit patch.diff
- # Compile; run the test suite
- hg commit
+ cd ../3.2
+ hg graft 2.7
-With the patch now committed, you want to merge the patch up into Python 3.4.
-This should be done *before* pushing your changes to hg.python.org, so that
-the branches are in sync on the public repository. Assuming you are doing
-all of your work in a single clone, do::
+This will port the latest changeset committed in the 2.7 clone to the 3.2 clone.
+``hg graft`` always commits automatically, except in case of conflicts, when
+you have to resolve them and run ``hg graft --continue`` afterwards.
+Instead of the branch name you can also specify a changeset id, and you can
+also graft changesets from 3.x to 2.7.
- hg update default
- hg merge 3.3
- # Fix any conflicts; compile; run the test suite
- hg commit
+On older version of Mercurial where ``hg graft`` is not available, you can use::
-.. index:: null merging
+ cd ../3.2
+ hg export 2.7 | hg import -
-.. note::
- If the patch should *not* be ported from Python 3.3 to Python 3.4, you must
- also make this explicit by doing a *null merge*: merge the changes but
- revert them before committing::
+The result will be the same, but in case of conflict this will create ``.rej``
+files rather than using Mercurial merge capabilities.
- hg update default
- hg merge 3.3
- hg revert -ar default
- hg resolve -am # needed only if the merge created conflicts
- hg commit
+A third option is to apply manually the patch on ``3.2``. This is convenient
+when there are too many differences with ``2.7`` or when there is already a
+specific patch for ``3.2``.
- This is necessary so that the merge gets recorded; otherwise, somebody
- else will have to make a decision about your patch when they try to merge.
- (Using a three-way merge tool generally makes the ``hg resolve`` step
- in the above unnecessary; also see `this bug report
- <http://bz.selenic.com/show_bug.cgi?id=2706>`__.)
-
-When you have finished your porting work (you can port several patches one
-after another in your local repository), you can push **all** outstanding
-changesets to hg.python.org::
-
- hg push
-
-This will push changes in both the Python 3.3 and Python 3.4 branches to
-hg.python.org.
-
-
-Porting Between Major Versions
-''''''''''''''''''''''''''''''
-
-Let's say you have committed your changes as changeset ``a7df1a869e4a``
-in the 3.3 branch and now want to port it to 2.7. This is simple using
-the "graft" command, which uses Mercurial's merge functionality to
-cherry-pick::
-
- hg update 2.7
- hg graft a7df1a869e4a
- # Compile; run the test suite
-
-Graft always commits automatically, except in case of conflicts, when you
-have to resolve them and run ``hg graft --continue`` afterwards.
-
-Another method is using "export" and "import": this has the advantage that
-you can run the test suite before committing, but the disadvantage that
-in case of conflicts, you will only get ``.rej`` files, not inline merge
-markers. ::
-
- hg update 2.7
- hg export a7df1a869e4a | hg import --no-commit -
- # Compile; run the test suite
- hg commit
-
-
-Using several working copies
-''''''''''''''''''''''''''''
-
-If you often work on bug fixes, you may want to avoid switching branches
-in your local repository. The reason is that rebuilding takes time
-when many files are updated. Instead, it is desirable to use a separate
-working copy for each maintenance branch.
-
-There are various ways to achieve this, but here is a possible scenario:
-
-* First do a clone of the public repository, whose working copy will be
- updated to the ``default`` branch::
-
- $ hg clone ssh://hg@hg.python.org/cpython py3k
-
-* Then clone it to create another local repository which is then used to
- checkout branch 3.3::
-
- $ hg clone py3k py3.3
- $ cd py3.3
- $ hg update 3.3
-
-* Then clone it to create another local repository which is then used to
- checkout branch 3.2::
-
- $ hg clone py3.3 py3.2
- $ cd py3.2
- $ hg update 3.2
-
-* If you also need the 3.1 branch to work on security fixes, you can similarly
- clone it, either from the ``py3.2`` or the ``py3k`` repository. It is
- suggested, though, that you clone from ``py3.2`` as that it will force you
- to push changes back up your clone chain so that you make sure to port
- changes to all proper versions.
-
-* You can also clone a 2.7-dedicated repository from the ``py3k`` branch::
-
- $ hg clone py3k py2.7
- $ cd py2.7
- $ hg update 2.7
-
-Given this arrangement of local repositories, pushing from the ``py3.2``
-repository will update the ``py3.3`` repository, where you can then merge your
-3.2 changes into the 3.3 branch. In turn, pushing changes from the ``py3.3``
-repository will update the ``py3k`` repository. Finally, once you have
-merged (and tested!) your ``3.3`` changes into the ``default`` branch, pushing
-from the ``py3k`` repository will publish your changes in the public
-repository.
-
-When working with this kind of arrangement, it can be useful to have a simple
-script that runs the necessary commands to update all branches with upstream
-changes::
-
- cd ~/py3k
- hg pull -u
- cd ~/py3.3
- hg pull -u
- cd ~/py3.2
- hg pull -u
- cd ~/py2.7
- hg pull -u
-
-Only the first of those updates will touch the network - the latter two will
-just transfer the changes locally between the relevant repositories.
-
-If you want, you can later :ref:`change the flow of changes <hg-paths>` implied
-by the cloning of repositories. For example, you may choose to add a separate
-``sandbox`` repository for experimental code (potentially published somewhere
-other than python.org) or an additional pristine repository that is
-never modified locally.
-
-
-Differences with ``svnmerge``
-'''''''''''''''''''''''''''''
-
-If you are coming from Subversion, you might be surprised by Mercurial
-:ref:`merges <hg-merge>`.
-Despite its name, ``svnmerge`` is different from ``hg merge``: while ``svnmerge``
-allows to cherry-pick individual revisions, ``hg merge`` can only merge whole
-lines of development in the repository's :abbr:`DAG (directed acyclic graph)`.
-Therefore, ``hg merge`` might force you to review outstanding changesets by
-someone else that haven't been merged yet.
-
-
-.. seealso::
- `Merging work
- <http://hgbook.red-bean.com/read/a-tour-of-mercurial-merging-work.html>`_,
- in `Mercurial: The Definitive Guide <http://hgbook.red-bean.com/>`_.
+.. warning::
+ Never use ``hg merge`` to port changes between 2.x and 3.x (or vice versa).
Long-term development of features
--
Repository URL: http://hg.python.org/devguide
More information about the Python-checkins
mailing list