summaryrefslogtreecommitdiff
path: root/docs/internals/contributing/writing-code/working-with-git.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/internals/contributing/writing-code/working-with-git.txt')
-rw-r--r--docs/internals/contributing/writing-code/working-with-git.txt222
1 files changed, 222 insertions, 0 deletions
diff --git a/docs/internals/contributing/writing-code/working-with-git.txt b/docs/internals/contributing/writing-code/working-with-git.txt
new file mode 100644
index 0000000000..dee9b9e074
--- /dev/null
+++ b/docs/internals/contributing/writing-code/working-with-git.txt
@@ -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``.