mirror of
https://github.com/django/django.git
synced 2025-08-30 15:27:40 +00:00
Fixed #18436 -- Updated contributing docs for git.
Most of the credit for this large patch goes to Anssi Kääriäinen. Many thanks to all the people who contributed to the discussion.
This commit is contained in:
parent
1a412dda62
commit
90fb6a4648
12 changed files with 626 additions and 483 deletions
|
@ -1,171 +0,0 @@
|
|||
=============
|
||||
Branch policy
|
||||
=============
|
||||
|
||||
In general, the trunk must be kept stable. People should be able to run
|
||||
production sites against the trunk at any time. Additionally, commits to trunk
|
||||
ought to be as atomic as possible -- smaller changes are better. Thus, large
|
||||
feature changes -- that is, changes too large to be encapsulated in a single
|
||||
patch, or changes that need multiple eyes on them -- must happen on dedicated
|
||||
branches.
|
||||
|
||||
This means that if you want to work on a large feature -- anything that would
|
||||
take more than a single patch, or requires large-scale refactoring -- you need
|
||||
to do it on a feature branch. Our development process recognizes two options
|
||||
for feature branches:
|
||||
|
||||
1. Feature branches using a distributed revision control system like
|
||||
Git_, Mercurial_, Bazaar_, etc.
|
||||
|
||||
If you're familiar with one of these tools, this is probably your best
|
||||
option since it doesn't require any support or buy-in from the Django
|
||||
core developers.
|
||||
|
||||
However, do keep in mind that Django will continue to use Subversion
|
||||
for the foreseeable future, and this will naturally limit the
|
||||
recognition of your branch. Further, if your branch becomes eligible
|
||||
for merging to trunk you'll need to find a core developer familiar
|
||||
with your DVCS of choice who'll actually perform the merge.
|
||||
|
||||
If you do decided to start a distributed branch of Django and choose to
|
||||
make it public, please add the branch to the `Django branches`_ wiki
|
||||
page.
|
||||
|
||||
2. Feature branches using SVN have a higher bar. If you want a branch
|
||||
in SVN itself, you'll need a "mentor" among the :doc:`core committers
|
||||
</internals/committers>`. This person is responsible for actually
|
||||
creating the branch, monitoring your process (see below), and
|
||||
ultimately merging the branch into trunk.
|
||||
|
||||
If you want a feature branch in SVN, you'll need to ask in
|
||||
`django-developers`_ for a mentor.
|
||||
|
||||
.. _git: http://git-scm.com/
|
||||
.. _mercurial: http://mercurial.selenic.com/
|
||||
.. _bazaar: http://bazaar.canonical.com/
|
||||
.. _django branches: https://code.djangoproject.com/wiki/DjangoBranches
|
||||
|
||||
Branch rules
|
||||
------------
|
||||
|
||||
We've got a few rules for branches born out of experience with what makes a
|
||||
successful Django branch.
|
||||
|
||||
DVCS branches are obviously not under central control, so we have no way of
|
||||
enforcing these rules. However, if you're using a DVCS, following these rules
|
||||
will give you the best chance of having a successful branch (read: merged back
|
||||
to trunk).
|
||||
|
||||
Developers with branches in SVN, however, **must** follow these rules. The
|
||||
branch mentor will keep on eye on the branch and **will delete it** if these
|
||||
rules are broken.
|
||||
|
||||
* Only branch entire copies of the Django tree, even if work is only
|
||||
happening on part of that tree. This makes it painless to switch to a
|
||||
branch.
|
||||
|
||||
* Merge changes from trunk no less than once a week, and preferably every
|
||||
couple-three days.
|
||||
|
||||
In our experience, doing regular trunk merges is often the difference
|
||||
between a successful branch and one that fizzles and dies.
|
||||
|
||||
If you're working on an SVN branch, you should be using `svnmerge.py`_
|
||||
to track merges from trunk.
|
||||
|
||||
* Keep tests passing and documentation up-to-date. As with patches,
|
||||
we'll only merge a branch that comes with tests and documentation.
|
||||
|
||||
.. _svnmerge.py: http://www.orcaware.com/svn/wiki/Svnmerge.py
|
||||
|
||||
Once the branch is stable and ready to be merged into the trunk, alert
|
||||
`django-developers`_.
|
||||
|
||||
After a branch has been merged, it should be considered "dead"; write access
|
||||
to it will be disabled, and old branches will be periodically "trimmed."
|
||||
To keep our SVN wrangling to a minimum, we won't be merging from a given
|
||||
branch into the trunk more than once.
|
||||
|
||||
Using branches
|
||||
--------------
|
||||
|
||||
To use a branch, you'll need to do two things:
|
||||
|
||||
* Get the branch's code through Subversion.
|
||||
|
||||
* Point your Python ``site-packages`` directory at the branch's version of
|
||||
the ``django`` package rather than the version you already have
|
||||
installed.
|
||||
|
||||
Getting the code from Subversion
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To get the latest version of a branch's code, check it out using Subversion:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
svn co https://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
|
||||
...where ``<branch>`` is the branch's name. See the `list of branch names`_.
|
||||
|
||||
Alternatively, you can automatically convert an existing directory of the
|
||||
Django source code as long as you've checked it out via Subversion. To do the
|
||||
conversion, execute this command from within your ``django`` directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
svn switch https://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
|
||||
The advantage of using ``svn switch`` instead of ``svn co`` is that the
|
||||
``switch`` command retains any changes you might have made to your local copy
|
||||
of the code. It attempts to merge those changes into the "switched" code. The
|
||||
disadvantage is that it may cause conflicts with your local changes if the
|
||||
"switched" code has altered the same lines of code.
|
||||
|
||||
(Note that if you use ``svn switch``, you don't need to point Python at the
|
||||
new version, as explained in the next section.)
|
||||
|
||||
.. _list of branch names: https://code.djangoproject.com/browser/django/branches
|
||||
|
||||
.. _pointing-python-at-the-new-django-version:
|
||||
|
||||
Pointing Python at the new Django version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you've retrieved the branch's code, you'll need to change your Python
|
||||
``site-packages`` directory so that it points to the branch version of the
|
||||
``django`` directory. (The ``site-packages`` directory is somewhere such as
|
||||
``/usr/lib/python2.7/site-packages`` or
|
||||
``/usr/local/lib/python2.7/site-packages`` or ``C:\Python\site-packages``.)
|
||||
|
||||
The simplest way to do this is by renaming the old ``django`` directory to
|
||||
``django.OLD`` and moving the trunk version of the code into the directory
|
||||
and calling it ``django``.
|
||||
|
||||
Alternatively, you can use a symlink called ``django`` that points to the
|
||||
location of the branch's ``django`` package. If you want to switch back, just
|
||||
change the symlink to point to the old code.
|
||||
|
||||
A third option is to use a path file (``<something>.pth``). This is a feature of
|
||||
the :mod:`site` module. First, make sure there are no files, directories or
|
||||
symlinks named ``django`` in your ``site-packages`` directory. Then create a
|
||||
text file named ``django.pth`` and save it to your ``site-packages`` directory.
|
||||
That file should contain a path to your copy of Django on a single line and
|
||||
optional comments. Here is an example that points to multiple branches. Just
|
||||
uncomment the line for the branch you want to use ('trunk' in this example) and
|
||||
make sure all other lines are commented::
|
||||
|
||||
# Trunk is a svn checkout of:
|
||||
# https://code.djangoproject.com/svn/django/trunk/
|
||||
#
|
||||
/path/to/trunk
|
||||
|
||||
# <branch> is a svn checkout of:
|
||||
# https://code.djangoproject.com/svn/django/branches/<branch>/
|
||||
#
|
||||
#/path/to/<branch>
|
||||
|
||||
# On windows a path may look like this:
|
||||
# C:/path/to/<branch>
|
||||
|
||||
.. _django-developers: http://groups.google.com/group/django-developers
|
|
@ -12,4 +12,4 @@ chances to be included in Django core:
|
|||
coding-style
|
||||
unit-tests
|
||||
submitting-patches
|
||||
branch-policy
|
||||
working-with-git
|
||||
|
|
|
@ -6,6 +6,15 @@ We're always grateful for patches to Django's code. Indeed, bug reports
|
|||
with associated patches will get fixed *far* more quickly than those
|
||||
without patches.
|
||||
|
||||
Typo fixes and trivial documentation changes
|
||||
--------------------------------------------
|
||||
|
||||
If you are fixing a really trivial issue, for example changing a word in the
|
||||
documentation, the preferred way to provide the patch is using GitHub pull
|
||||
requests without a Trac ticket. Trac tickets are still acceptable.
|
||||
|
||||
See the :doc:`working-with-git` for more details on how to use pull requests.
|
||||
|
||||
"Claiming" tickets
|
||||
------------------
|
||||
|
||||
|
@ -69,38 +78,16 @@ Of course, going through the steps of claiming tickets is overkill in some
|
|||
cases. In the case of small changes, such as typos in the documentation or
|
||||
small bugs that will only take a few minutes to fix, you don't need to jump
|
||||
through the hoops of claiming tickets. Just submit your patch and be done with
|
||||
it.
|
||||
it. Of course, it is always acceptable, regardless of the ticket's ownership
|
||||
status, to submit patches to a ticket if you happen to have a patch ready.
|
||||
|
||||
.. _patch-style:
|
||||
|
||||
Patch style
|
||||
-----------
|
||||
|
||||
* Make sure your code matches our :doc:`coding-style`.
|
||||
|
||||
* Submit patches in the format returned by the ``svn diff`` command.
|
||||
An exception is for code changes that are described more clearly in
|
||||
plain English than in code. Indentation is the most common example; it's
|
||||
hard to read patches when the only difference in code is that it's
|
||||
indented.
|
||||
|
||||
Patches in ``git diff`` format are also acceptable.
|
||||
|
||||
* When creating patches, always run ``svn diff`` from the top-level
|
||||
``trunk`` directory -- i.e. the one that contains ``django``, ``docs``,
|
||||
``tests``, ``AUTHORS``, etc. This makes it easy for other people to
|
||||
apply your patches.
|
||||
|
||||
* Attach patches to a ticket in the `ticket tracker`_, using the "attach
|
||||
file" button. Please *don't* put the patch in the ticket description
|
||||
or comment unless it's a single line patch.
|
||||
|
||||
* Name the patch file with a ``.diff`` extension; this will let the ticket
|
||||
tracker apply correct syntax highlighting, which is quite helpful.
|
||||
|
||||
* Check the "Has patch" box on the ticket details. This will make it
|
||||
obvious that the ticket includes a patch, and it will add the ticket to
|
||||
the `list of tickets with patches`_.
|
||||
Make sure that any contribution you do fulfills at least the following
|
||||
requirements:
|
||||
|
||||
* The code required to fix a problem or add a feature is an essential part
|
||||
of a patch, but it is not the only part. A good patch should also
|
||||
|
@ -114,6 +101,37 @@ Patch style
|
|||
behavior of an existing feature, the patch should also contain
|
||||
documentation.
|
||||
|
||||
You can use either GitHub branches and pull requests or direct patches
|
||||
to publish your work. If you use the Git workflow, then you should
|
||||
announce your branch in the ticket by including a link to your branch.
|
||||
When you think your work is ready to be merged in create a pull request.
|
||||
See the :doc:`working-with-git` documentation for mode details.
|
||||
|
||||
You can also use patches in Trac. When using this style, follow these
|
||||
guidelines.
|
||||
|
||||
* Submit patches in the format returned by the ``git diff`` command.
|
||||
An exception is for code changes that are described more clearly in
|
||||
plain English than in code. Indentation is the most common example; it's
|
||||
hard to read patches when the only difference in code is that it's
|
||||
indented.
|
||||
|
||||
* Attach patches to a ticket in the `ticket tracker`_, using the "attach
|
||||
file" button. Please *don't* put the patch in the ticket description
|
||||
or comment unless it's a single line patch.
|
||||
|
||||
* Name the patch file with a ``.diff`` extension; this will let the ticket
|
||||
tracker apply correct syntax highlighting, which is quite helpful.
|
||||
|
||||
Regardless of the way you submit your work, follow these steps.
|
||||
|
||||
* Make sure your code matches our :doc:`coding-style`.
|
||||
|
||||
* Check the "Has patch" box on the ticket details. This will make it
|
||||
obvious that the ticket includes a patch, and it will add the ticket to
|
||||
the `list of tickets with patches`_.
|
||||
|
||||
|
||||
Non-trivial patches
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -36,9 +36,7 @@ with this sample ``settings`` module, ``cd`` into the Django
|
|||
./runtests.py --settings=test_sqlite
|
||||
|
||||
If you get an ``ImportError: No module named django.contrib`` error,
|
||||
you need to add your install of Django to your ``PYTHONPATH``. For
|
||||
more details on how to do this, read
|
||||
:ref:`pointing-python-at-the-new-django-version`.
|
||||
you need to add your install of Django to your ``PYTHONPATH``.
|
||||
|
||||
Using another ``settings`` module
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
222
docs/internals/contributing/writing-code/working-with-git.txt
Normal file
222
docs/internals/contributing/writing-code/working-with-git.txt
Normal file
|
@ -0,0 +1,222 @@
|
|||
Working with Git and GitHub
|
||||
===========================
|
||||
|
||||
Django uses `Git`_ for its source control. You can `download
|
||||
<http://git-scm.com/download>`_ Git, but it's often easier to install with
|
||||
your operating system's package manager.
|
||||
|
||||
Django's `Git repository`_ is hosted on `GitHub`_, and it is recommended
|
||||
that you also work using GitHub.
|
||||
|
||||
After installing Git the first thing you should do is setup your name and
|
||||
email::
|
||||
|
||||
$ git config --global user.name "Firstname Lastname"
|
||||
$ git config --global user.email "your_email@youremail.com"
|
||||
|
||||
Note that ``user.name`` should be your real name, not your GitHub nick. GitHub
|
||||
should know the email you use in the ``user.email`` field, as this will be
|
||||
used to associate your commits with your GitHub account.
|
||||
|
||||
Now we are going to show how to create a GitHub pull request containing the
|
||||
changes for Trac ticket #xxxxx. By creating a fully ready pull request you
|
||||
will make the committers' job easier, and thus your work is more likely to be
|
||||
merged into Django. You can also upload a traditional patch to Trac, but it's
|
||||
less practical for reviews.
|
||||
|
||||
.. _Git: http://git-scm.com/
|
||||
.. _GitHub: https://github.com/
|
||||
.. _Git repository: https://github.com/django/django/
|
||||
|
||||
Setting up local repository
|
||||
---------------------------
|
||||
|
||||
When you have created a GitHub account, with the nick "github_nick", and
|
||||
forked Django's repository, you should create a local copy of your fork::
|
||||
|
||||
git clone git@github.com:github_nick/django.git
|
||||
|
||||
This will create a new directory "django" containing a clone of your GitHub
|
||||
repository. Your GitHub repository will be called "origin" in Git. You should
|
||||
also setup django/django as an "upstream" remote::
|
||||
|
||||
git remote add upstream git@github.com:django/django.git
|
||||
git fetch upstream
|
||||
|
||||
You can add other remotes similarly, for example::
|
||||
|
||||
git remote add akaariai git@github.com:akaariai/django.git
|
||||
|
||||
Working on a ticket
|
||||
-------------------
|
||||
|
||||
When working on a ticket you will almost always want to create a new branch
|
||||
for the work, and base that work on upstream/master::
|
||||
|
||||
git checkout -b ticket_xxxxx upstream/master
|
||||
|
||||
If you are working for a fix on the 1.4 branch, you would instead do::
|
||||
|
||||
git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
|
||||
|
||||
Assume the work is carried on ticket_xxxxx branch. Make some changes and
|
||||
commit them::
|
||||
|
||||
git commit
|
||||
|
||||
When writing the commit message, you should follow the :ref:`commit message
|
||||
guidelines <committing-guidlines>` to ease the work of the committer. If
|
||||
you're uncomfortable with English, try at least to describe precisely what the
|
||||
commit does.
|
||||
|
||||
If you need to do additional work on your branch, commit as often as
|
||||
necessary::
|
||||
|
||||
git commit -m 'Added two more tests for edge cases'
|
||||
|
||||
Publishing work
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
You can publish your work on GitHub by just using::
|
||||
|
||||
git push origin ticket_xxxxx
|
||||
|
||||
When you go to your GitHub page you will notice a new branch has been created.
|
||||
If you are working on a Trac ticket, you should mention in the ticket that
|
||||
your work is available from branch ticket_xxxxx of your github repo. Include a
|
||||
link to your branch.
|
||||
|
||||
Note that the above branch is called a "topic branch" in Git parlance. This
|
||||
means that other people should not base their work on your branch. In
|
||||
particular this means you are free to rewrite the history of this branch (by
|
||||
using ``git rebase`` for example). There are also "public branches". These are
|
||||
branches other people are supposed to fork, and thus their history should
|
||||
never change. Good examples of public branches are the ``master`` and
|
||||
``stable/A.B.x`` branches in the django/django repository.
|
||||
|
||||
When you think your work is ready to be pulled into Django, you should create
|
||||
a pull request at GitHub. A good pull request contains:
|
||||
|
||||
* Commits with one logical change in each, following the
|
||||
:doc:`coding style <coding-style>`.
|
||||
|
||||
* Well formed messages for each commit: a summary line and then paragraphs
|
||||
wrapped at 72 characters thereafter. See the :ref:`committing guidelines
|
||||
<committing-guidlines>` for more details.
|
||||
|
||||
* Documentation and tests, if needed. Actually tests are always needed, except
|
||||
for documentation changes.
|
||||
|
||||
* The test suite passes and the documentation builds without warnings.
|
||||
|
||||
Once you have created your pull request, you should add a comment in the
|
||||
related Trac ticket explaining what you've done. In particular you should tell
|
||||
in which environment you've run the tests, for instance: "all tests pass under
|
||||
SQLite and MySQL".
|
||||
|
||||
Your pull request should be ready for merging into Django. Pull requests at
|
||||
GitHub have only two states: open and closed. The committers who deals with
|
||||
your pull request has only two options: merge it or close it. For this reason,
|
||||
it isn't useful to make a pull request until the code is ready for merging --
|
||||
or sufficiently close that a committer will finish it himself.
|
||||
|
||||
Rebasing branches
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the example above you created two commits, the "Fixed ticket_xxxxx" commit
|
||||
and "Added two more tests" commit. We do not want to have the "Added two more
|
||||
tests" commit in the Django's repository as it would just be useless noise.
|
||||
Instead, we would like to only have one commit. To rework the history of your
|
||||
branch you can squash the commits into one by using interactive rebase::
|
||||
|
||||
git rebase -i HEAD~2
|
||||
|
||||
The HEAD~2 above is shorthand for two latest commits. The above command
|
||||
will open an editor showing the two commits, prefixed with the word "pick".
|
||||
You should change the second line to "squash" instead. This will keep the
|
||||
first commit, and squash the second commit to the first one. Save and quit
|
||||
the editor. A second editor window should open. Here you can reword the
|
||||
commit message for the commit.
|
||||
|
||||
You can also use the "edit" option in rebase. This way you can change a single
|
||||
commit. For example::
|
||||
|
||||
git rebase -i HEAD~3
|
||||
# Choose edit, pick, pick for the commits
|
||||
# Now you are able to rework the commit (use git add normally to add changes)
|
||||
# When finished, commit work with "--amend" and continue
|
||||
git commit --amend
|
||||
# reword the commit message if needed
|
||||
git rebase --continue
|
||||
# The second and third commit should be applied.
|
||||
|
||||
If you need to change an already published topic branch at GitHub, you will
|
||||
need to force-push the changes::
|
||||
|
||||
git push -f origin ticket_xxxxx
|
||||
|
||||
Note that this will rewrite history of ticket_xxxxx - if you check the commit
|
||||
hashes before and after the operation at GitHub you will notice that the
|
||||
commit hashes do not match any more. This is acceptable, as the branch is topic
|
||||
branch, and nobody should be basing their work on this branch.
|
||||
|
||||
After upstream has changed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When upstream (django/django) has changed, you should rebase your work. To
|
||||
do this, use::
|
||||
|
||||
git fetch upstream
|
||||
git rebase
|
||||
|
||||
The work is automatically rebased using the branch you forked on, in the
|
||||
example case using upstream/master.
|
||||
|
||||
The rebase command removes all your local commits temporarily, applies the
|
||||
upstream commits, and then applies your local commits again on the work. If
|
||||
there are merge conflicts you will need to resolve them and then use ``git
|
||||
rebase --continue``. At any point you can use ``git rebase --abort`` to return
|
||||
to the original state.
|
||||
|
||||
Note that you want to rebase on upstream, not merge the upstream. The reason
|
||||
for this is that by rebasing, your commits will always be on top of the
|
||||
upstream's work, not mixed with the changes in the upstream. This way your
|
||||
branch only contains commits related to its topic, and this makes squashing
|
||||
easier.
|
||||
|
||||
After review
|
||||
------------
|
||||
|
||||
It is unusual to get any non-trivial amount of code into core without changes
|
||||
requested by reviewers. In this case, it is often a good idea to add the
|
||||
changes as one incremental commit to your work. This allows the reviewer to
|
||||
easily check what changes you have done::
|
||||
|
||||
# Do changes required by the reviewer, commit often.
|
||||
# Before publishing the changes, rebase your work. Assume you added two
|
||||
# commits to the work.
|
||||
git rebase -i HEAD~2
|
||||
# squash the second commit into the first, write a commit message something
|
||||
# like this:
|
||||
Made changes asked in review by the_reviewer
|
||||
|
||||
- Fixed whitespace errors in foo/bar
|
||||
- Reworded the doc string of the_method()
|
||||
|
||||
# Push your work back to your github repo, there should not be any need
|
||||
# for force (-f) push, as you didn't touch the public commits in the rebase.
|
||||
git push origin ticket_xxxxx
|
||||
# Check your pull request, it should now contain the new commit, too.
|
||||
|
||||
The committer is likely to squash the review commit into the previous commit
|
||||
when committing the code.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
* Work on GitHub if possible.
|
||||
* Announce your work on the Trac ticket by linking to your GitHub branch.
|
||||
* When you have something ready, make a pull request.
|
||||
* Make your pull requests as good as you can.
|
||||
* When doing fixes to your work, use ``git rebase -i`` to squash the commits.
|
||||
* When upstream has changed, do ``git fetch upstream; git rebase``.
|
Loading…
Add table
Add a link
Reference in a new issue