working-with-git.txt 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. Working with Git and GitHub
  2. ===========================
  3. Django uses `Git`_ for its source control. You can `download
  4. <http://git-scm.com/download>`_ Git, but it's often easier to install with
  5. your operating system's package manager.
  6. Django's `Git repository`_ is hosted on `GitHub`_, and it is recommended
  7. that you also work using GitHub.
  8. After installing Git the first thing you should do is setup your name and
  9. email::
  10. $ git config --global user.name "Firstname Lastname"
  11. $ git config --global user.email "your_email@youremail.com"
  12. Note that ``user.name`` should be your real name, not your GitHub nick. GitHub
  13. should know the email you use in the ``user.email`` field, as this will be
  14. used to associate your commits with your GitHub account.
  15. Now we are going to show how to create a GitHub pull request containing the
  16. changes for Trac ticket #xxxxx. By creating a fully ready pull request you
  17. will make the committers' job easier, and thus your work is more likely to be
  18. merged into Django. You can also upload a traditional patch to Trac, but it's
  19. less practical for reviews.
  20. .. _Git: http://git-scm.com/
  21. .. _GitHub: https://github.com/
  22. .. _Git repository: https://github.com/django/django/
  23. Setting up local repository
  24. ---------------------------
  25. When you have created a GitHub account, with the nick "github_nick", and
  26. forked Django's repository, you should create a local copy of your fork::
  27. git clone git@github.com:github_nick/django.git
  28. This will create a new directory "django" containing a clone of your GitHub
  29. repository. Your GitHub repository will be called "origin" in Git. You should
  30. also setup django/django as an "upstream" remote::
  31. git remote add upstream git@github.com:django/django.git
  32. git fetch upstream
  33. You can add other remotes similarly, for example::
  34. git remote add akaariai git@github.com:akaariai/django.git
  35. Working on a ticket
  36. -------------------
  37. When working on a ticket you will almost always want to create a new branch
  38. for the work, and base that work on upstream/master::
  39. git checkout -b ticket_xxxxx upstream/master
  40. If you are working for a fix on the 1.4 branch, you would instead do::
  41. git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
  42. Assume the work is carried on ticket_xxxxx branch. Make some changes and
  43. commit them::
  44. git commit
  45. When writing the commit message, you should follow the :ref:`commit message
  46. guidelines <committing-guidlines>` to ease the work of the committer. If
  47. you're uncomfortable with English, try at least to describe precisely what the
  48. commit does.
  49. If you need to do additional work on your branch, commit as often as
  50. necessary::
  51. git commit -m 'Added two more tests for edge cases'
  52. Publishing work
  53. ~~~~~~~~~~~~~~~
  54. You can publish your work on GitHub by just using::
  55. git push origin ticket_xxxxx
  56. When you go to your GitHub page you will notice a new branch has been created.
  57. If you are working on a Trac ticket, you should mention in the ticket that
  58. your work is available from branch ticket_xxxxx of your github repo. Include a
  59. link to your branch.
  60. Note that the above branch is called a "topic branch" in Git parlance. This
  61. means that other people should not base their work on your branch. In
  62. particular this means you are free to rewrite the history of this branch (by
  63. using ``git rebase`` for example). There are also "public branches". These are
  64. branches other people are supposed to fork, and thus their history should
  65. never change. Good examples of public branches are the ``master`` and
  66. ``stable/A.B.x`` branches in the django/django repository.
  67. When you think your work is ready to be pulled into Django, you should create
  68. a pull request at GitHub. A good pull request contains:
  69. * Commits with one logical change in each, following the
  70. :doc:`coding style <coding-style>`.
  71. * Well formed messages for each commit: a summary line and then paragraphs
  72. wrapped at 72 characters thereafter. See the :ref:`committing guidelines
  73. <committing-guidlines>` for more details.
  74. * Documentation and tests, if needed. Actually tests are always needed, except
  75. for documentation changes.
  76. * The test suite passes and the documentation builds without warnings.
  77. Once you have created your pull request, you should add a comment in the
  78. related Trac ticket explaining what you've done. In particular you should tell
  79. in which environment you've run the tests, for instance: "all tests pass under
  80. SQLite and MySQL".
  81. Your pull request should be ready for merging into Django. Pull requests at
  82. GitHub have only two states: open and closed. The committers who deals with
  83. your pull request has only two options: merge it or close it. For this reason,
  84. it isn't useful to make a pull request until the code is ready for merging --
  85. or sufficiently close that a committer will finish it himself.
  86. Rebasing branches
  87. ~~~~~~~~~~~~~~~~~
  88. In the example above you created two commits, the "Fixed ticket_xxxxx" commit
  89. and "Added two more tests" commit. We do not want to have the "Added two more
  90. tests" commit in the Django's repository as it would just be useless noise.
  91. Instead, we would like to only have one commit. To rework the history of your
  92. branch you can squash the commits into one by using interactive rebase::
  93. git rebase -i HEAD~2
  94. The HEAD~2 above is shorthand for two latest commits. The above command
  95. will open an editor showing the two commits, prefixed with the word "pick".
  96. You should change the second line to "squash" instead. This will keep the
  97. first commit, and squash the second commit to the first one. Save and quit
  98. the editor. A second editor window should open. Here you can reword the
  99. commit message for the commit.
  100. You can also use the "edit" option in rebase. This way you can change a single
  101. commit. For example::
  102. git rebase -i HEAD~3
  103. # Choose edit, pick, pick for the commits
  104. # Now you are able to rework the commit (use git add normally to add changes)
  105. # When finished, commit work with "--amend" and continue
  106. git commit --amend
  107. # reword the commit message if needed
  108. git rebase --continue
  109. # The second and third commit should be applied.
  110. If you need to change an already published topic branch at GitHub, you will
  111. need to force-push the changes::
  112. git push -f origin ticket_xxxxx
  113. Note that this will rewrite history of ticket_xxxxx - if you check the commit
  114. hashes before and after the operation at GitHub you will notice that the
  115. commit hashes do not match any more. This is acceptable, as the branch is topic
  116. branch, and nobody should be basing their work on this branch.
  117. After upstream has changed
  118. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  119. When upstream (django/django) has changed, you should rebase your work. To
  120. do this, use::
  121. git fetch upstream
  122. git rebase
  123. The work is automatically rebased using the branch you forked on, in the
  124. example case using upstream/master.
  125. The rebase command removes all your local commits temporarily, applies the
  126. upstream commits, and then applies your local commits again on the work. If
  127. there are merge conflicts you will need to resolve them and then use ``git
  128. rebase --continue``. At any point you can use ``git rebase --abort`` to return
  129. to the original state.
  130. Note that you want to rebase on upstream, not merge the upstream. The reason
  131. for this is that by rebasing, your commits will always be on top of the
  132. upstream's work, not mixed with the changes in the upstream. This way your
  133. branch only contains commits related to its topic, and this makes squashing
  134. easier.
  135. After review
  136. ------------
  137. It is unusual to get any non-trivial amount of code into core without changes
  138. requested by reviewers. In this case, it is often a good idea to add the
  139. changes as one incremental commit to your work. This allows the reviewer to
  140. easily check what changes you have done::
  141. # Do changes required by the reviewer, commit often.
  142. # Before publishing the changes, rebase your work. Assume you added two
  143. # commits to the work.
  144. git rebase -i HEAD~2
  145. # squash the second commit into the first, write a commit message something
  146. # like this:
  147. Made changes asked in review by the_reviewer
  148. - Fixed whitespace errors in foo/bar
  149. - Reworded the doc string of the_method()
  150. # Push your work back to your github repo, there should not be any need
  151. # for force (-f) push, as you didn't touch the public commits in the rebase.
  152. git push origin ticket_xxxxx
  153. # Check your pull request, it should now contain the new commit, too.
  154. The committer is likely to squash the review commit into the previous commit
  155. when committing the code.
  156. Summary
  157. -------
  158. * Work on GitHub if possible.
  159. * Announce your work on the Trac ticket by linking to your GitHub branch.
  160. * When you have something ready, make a pull request.
  161. * Make your pull requests as good as you can.
  162. * When doing fixes to your work, use ``git rebase -i`` to squash the commits.
  163. * When upstream has changed, do ``git fetch upstream; git rebase``.