123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- ===========================
- Working with Git and GitHub
- ===========================
- This section explains how the community can contribute code to Django via pull
- requests. If you're interested in how :ref:`mergers <mergers-team>` handle
- them, see :doc:`../committing-code`.
- Below, 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 reviewer's job easier, meaning that your work is more likely to
- be merged into Django.
- You could also upload a traditional patch to Trac, but it's less practical for
- reviews.
- Installing Git
- ==============
- Django uses `Git`_ for its source control. You can `download
- <https://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 set up your name and
- email:
- .. code-block:: shell
- $ git config --global user.name "Your Real Name"
- $ git config --global user.email "you@email.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.
- .. _Git: https://git-scm.com/
- .. _Git repository: https://github.com/django/django/
- .. _GitHub: https://github.com/
- Setting up local repository
- ===========================
- When you have created your GitHub account, with the nick "GitHub_nick", and
- `forked Django's repository <https://github.com/django/django/fork>`__,
- create a local copy of your fork:
- .. code-block:: shell
- git clone https://github.com/GitHub_nick/django.git
- This will create a new directory "django", containing a clone of your GitHub
- repository. The rest of the git commands on this page need to be run within the
- cloned directory, so switch to it now:
- .. code-block:: shell
- cd django
- Your GitHub repository will be called "origin" in Git.
- You should also set up ``django/django`` as an "upstream" remote (that is, tell
- git that the reference Django repository was the source of your fork of it):
- .. code-block:: shell
- git remote add upstream https://github.com/django/django.git
- git fetch upstream
- You can add other remotes similarly, for example:
- .. code-block:: shell
- git remote add akaariai https://github.com/akaariai/django.git
- Working on a ticket
- ===================
- When working on a ticket, create a new branch for the work, and base that work
- on ``upstream/main``:
- .. code-block:: shell
- git checkout -b ticket_xxxxx upstream/main
- The -b flag creates a new branch for you locally. Don't hesitate to create new
- branches even for the smallest things - that's what they are there for.
- If instead you were working for a fix on the 1.4 branch, you would do:
- .. code-block:: shell
- git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
- Assume the work is carried on the ticket_xxxxx branch. Make some changes and
- commit them:
- .. code-block:: shell
- git commit
- When writing the commit message, follow the :ref:`commit message
- guidelines <committing-guidelines>` to ease the work of the merger. 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:
- .. code-block:: shell
- git commit -m 'Added two more tests for edge cases'
- Publishing work
- ---------------
- You can publish your work on GitHub by running:
- .. code-block:: shell
- 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. You are
- free to rewrite the history of this branch, by using ``git rebase`` for
- example. Other people shouldn't base their work on such a branch, because
- their clone would become corrupt when you edit commits.
- There are also "public branches". These are branches other people are supposed
- to fork, so the history of these branches should never change. Good examples
- of public branches are the ``main`` 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 means:
- * 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-guidelines>` for more details,
- * documentation and tests, if needed -- actually tests are always needed,
- except for documentation changes.
- The test suite must pass and the documentation must build 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 note
- the environment in which you ran the tests, for instance: "all tests pass
- under SQLite and MySQL".
- Pull requests at GitHub have only two states: open and closed. The merger who
- will deal 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 merger will finish it themselves.
- 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 entire history of your working process in your
- repository. Your commit "Added two more tests" would be unhelpful noise.
- Instead, we would rather only have one commit containing all your work.
- To rework the history of your branch you can squash the commits into one by
- using interactive rebase:
- .. code-block:: shell
- 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".
- Change "pick" on the second line to "squash" instead. This will keep the
- first commit, and squash the second commit into the first one. Save and quit
- the editor. A second editor window should open, so you can reword the
- commit message for the commit now that it includes both your steps.
- You can also use the "edit" option in rebase. This way you can change a single
- commit, for example to fix a typo in a docstring:
- .. code-block:: shell
- 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 commits should be applied.
- If your topic branch is already published at GitHub, for example if you're
- making minor changes to take into account a review, you will need to force-push
- the changes:
- .. code-block:: shell
- 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 anymore. This is acceptable, as the branch is a topic
- branch, and nobody should be basing their work on it.
- After upstream has changed
- --------------------------
- When upstream (``django/django``) has changed, you should rebase your work. To
- do this, use:
- .. code-block:: shell
- git fetch upstream
- git rebase upstream/main
- The work is automatically rebased using the branch you forked on, in the
- example case using ``upstream/main``.
- 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 in with* the changes in the upstream.
- This way your branch will contain only commits related to its topic, which
- 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.
- In this case, do the changes required by the reviewer. Commit as often as
- necessary. Before publishing the changes, rebase your work. If you added two
- commits, you would run:
- .. code-block:: shell
- git rebase -i HEAD~2
- Squash the second commit into the first. Write a commit message along the lines
- of:
- .. code-block:: text
- Made changes asked in review by <reviewer>
- - Fixed whitespace errors in foobar
- - Reworded the docstring of bar()
- Finally, push your work back to your GitHub repository. Since you didn't touch
- the public commits during the rebase, you should not need to force-push:
- .. code-block:: shell
- git push origin ticket_xxxxx
- Your pull request should now contain the new commit too.
- Note that the merger is likely to squash the review commit into the previous
- commit when committing the code.
- Working on a patch
- ==================
- One of the ways that developers can contribute to Django is by reviewing
- patches. Those patches will typically exist as pull requests on GitHub and
- can be easily integrated into your local repository:
- .. code-block:: shell
- git checkout -b pull_xxxxx upstream/main
- curl -L https://github.com/django/django/pull/xxxxx.patch | git am
- This will create a new branch and then apply the changes from the pull request
- to it. At this point you can run the tests or do anything else you need to
- do to investigate the quality of the patch.
- For more detail on working with pull requests see the
- :ref:`guidelines for mergers <handling-pull-requests>`.
- Summary
- =======
- * Work on GitHub if you can.
- * 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``.
|