Code


Version 26 (modified by mrts, 5 years ago) (diff)

--

Collaboration on GitHub

This page gives guidelines for distributed Django development.

It is not part of the official Django development process.

Prerequisites

1. Install git

If you want to learn more about git, see the git webpage or the git cheat sheet for a quick overview. PEP 0374 is also a good read.

OS X

Git OS X Installer or use MacPorts

$ sudo port install git-core

Ubuntu

If using a recent Ubuntu relase (9.04, 9.10 or later), you can install git from the main repository:

$ apt-get install git-core
Using recent git

However, if you either want to use the latest git version or use an older Ubuntu release, you can use the personal package archive that provides backports of the recent git version for all Ubuntu releases since Hardy.

Installation instructions:

  1. add the following line to /etc/apt/sources.list.d/git.list (substituting UBUNTU_RELEASE_NAME with the Ubuntu release you are using):
    deb http://ppa.launchpad.net/smartlounge/ubuntu UBUNTU_RELEASE_NAME main
    
  2. install git:
    $ apt-get update
    $ apt-get install git-core
    
  3. verify that the correct version was installed:
    $ git --version
    

2. Register an account on GitHub

Go to https://github.com/signup/free and follow the instructions.

Branchy development: working on several tasks in parallel

You want to work on several fixes and features (tasks) and want to

  • keep the changes for a particular task selt-contained in a branch,
  • frequently update the codebase with upstream changes,
  • have a has-it-all branch for testing out how the different task branches interact.

Initial setup

  1. Create a fork of the automatically updated Django SVN trunk mirror on GitHub by clicking fork at http://github.com/django/django/tree/master
  2. Clone the fork to your workstation:
    git clone git@github.com:YOUR_NICK_HERE/django.git
    
  3. Add the upstream Django SVN mirror for tracking:
    cd django
    git remote add upstream git://github.com/django/django.git
    git fetch upstream
    

Working on a task

Goal: keep the changes self-contained, create and update patches suitable for attaching to tickets in Django trac.

  1. Create a branch from master
    git checkout -b ticket1234 master
    
  2. Change files, commit often
    git commit -am "Changed foo."
    
  3. Run tests
  4. Create the remote branch and push changes into it
    git push origin ticket1234
    
  5. Create a patch, attach it to a relevant ticket in trac
    git diff master > ticket1234.patch
    

Repeat for every ticket you want to work on.

After upstream has changed

Goal: bring in the changes in upstream to a task.

  1. When the upstream Django SVN mirror is updated, pull the updates from it (fetching and merging in one step)
    git pull upstream master
    
  2. Switch to the ticket branch
    git checkout ticket1234
    
  3. Merge, fix any conflicts
    git merge master
    
  4. Run tests
  5. Push changes to GitHub (the remote branch was already created before)
    git push
    
  6. If the patch needs updating, create a new patch and attach it to the relevant ticket
    git diff master > ticket1234.patch
    

Repeat for every ticket you have worked on.

Testing everything in the has-it-all branch

Goal: a place to try out the code from several tasks together. master can not be used for this as it is used for tracking upstream. This is a temporary branch that can be removed after testing is done.

  1. Create the branch
    git checkout -b has-it-all master
    
  2. Merge in all task branches, fix any conflicts that occur in the task branches (i.e. they should merge cleanly)
    git merge ticket1234
    git merge ticket1235
    ...
    
  3. Run tests
  4. Delete the branch
    git checkout master
    git branch -d has-it-all
    

If something went wrong

The following may wreak havoc if someone has forked your branches. If not, it should be relatively safe.

On master

You can reset master to a one-to-one copy of upstream as follows:

git reset --hard upstream/master
git push --force

On a branch

You can manually remove or glue commits together with

git rebase -i master

To abort the rebase, just remove all non-commented lines.

You may need to use --force to push changes back to GitHub

git push --force

If something went wrong during rebase and you want to undo the rebase:

  1. Find out the state identifier before the rebase:
    git reflog
    
  2. Switch back to that state
    git reset --hard HEAD@{NUMBER_FROM_REFLOG_HERE}
    

This works for all other similar problems as well, e.g. for backing out a merge.

Collaboration on a large feature

The process should be managed with the Dictator and Lieutenants Workflow, described at http://whygitisbetterthanx.com/#any-workflow.

  • Dictators are core Django developers, who eventually merge the git branches back to Django trunk.
  • Lieutenants are developers, who take the responsibility of steering and coordinating the work on a large feature (e.g. aggregates).
  • Contributors are developers who contribute -- under lieutenant's guidance -- to the development of the feature.

The workflow described below should usually use a separate branch to keep the work isolated, so the instructions need updating.

Lieutenant

  1. Create a fork of the automatically updated Django SVN trunk mirror on GitHub by clicking fork at http://github.com/django/django/tree/master
  2. Describe the design of the feature you implement on the GitHub project wiki, list tasks that need tackling so that contributors can pick them easily.
  3. Clone the fork to your workstation:
    git clone git@github.com:YOUR_NICK_HERE/django.git
    
  4. Add the upstream Django SVN mirror for tracking:
    cd django
    git remote add upstream git://github.com/django/django.git
    git fetch upstream
    
  5. Work on code, commit locally as needed:
    git commit -a -m "Implemented foo."
    
  6. Publish changes to your public repository:
    git push
    
  7. When the upstream Django SVN mirror is updated, pull the updates from it (fetching and merging in one step):
    git pull upstream master
    
  8. When the feature is ready, get in contact with a core developer (the dictator) to integrate your work.

Managing contributor submissions

When a contributor feels that his updates are ready to be merged back to lieutenant's repository, he should submit a pull request to the lieutenant (see below).

When a lieutenant receives a pull request:

  1. Review the commit list that is listed in the pull request
  2. If everything looks good, pull code from the the contributor's repository (this creates a new branch, if the branch already exists, skip the remote add step):
    $ git remote add -f CONTRIBUTOR_NICK_HERE git://github.com/CONTRIBUTOR_NICK_HERE/django.git
    $ git checkout -b CONTRIBUTOR_NICK_HERE/master
    $ git pull CONTRIBUTOR_NICK_HERE master # for current or master:XXXXXXX, where XXXXXX is the changeset code received in pull request 
    
  3. Merge changes with the master branch:
    $ git checkout master
    $ git merge CONTRIBUTOR_NICK_HERE/master
    
  4. Run tests
  5. If tests pass, push changes to your public repository:
    $ git push
    

Contributor

Largely, this is a copy-paste of the lieutenant workflow, only the tracked repositories and the final step (pull request) differ.

  1. Create a fork of the lieutenant's repository on GitHub by clicking fork at e.g. http://github.com/LIEUTENANT_NICK_HERE/django/tree/master.
  2. Pick a task from the lieutenant's GitHub project wiki, update the wiki as needed.
  3. Clone the fork to your workstation:
    git clone git@github.com:YOUR_NICK_HERE/django.git
    
  4. Add the upstream lieutenant's repository for tracking:
    cd django
    git remote add upstream git://github.com/LIEUTENANT_NICK_HERE/django.git
    git fetch upstream
    
  5. Work on code, commit locally as needed:
    git commit -a -m "Implemented foo."
    
  6. Publish changes to your public repository:
    git push
    
  7. When the upstream lieutenant's repository is updated, pull the updates from it:
    git pull upstream master
    
  8. When the feature is ready, send the lieutenant a pull request by clicking pull request on your forked project's page.

Quality assurance

To assure that the contribution is in par with Django code quality standards, the actual development workflow should be similar to the following:

Contributor

  1. Implement tests for the features to be added
  2. Commit locally with a descriptive commit message
  3. Implement the features
  4. Commit locally
  5. Run the test suite iteratively, fixing whatever the tests indicate needs fixing
  6. Commit locally if something changed
  7. Push your changes to GitHub

Lieutenant

Specify the API and design of the feature on GitHub wiki, try to add documentation that specifies the behaviour before implementation.

Integrating contributor's work:

  1. Review contributor's changes (knowing that the contributor has assured that tests pass)
  2. Pull changes from contributor's repo to your repo
  3. Run the test suite
  4. Push changes to the public code hosting service
  5. Update docs if needed