Работа с Git и GitHub¶
Этот раздел объясняет, как сообщество может вносить код в Django с помощью запросов на исправление. Если вас интересует, как коммиттеры работают с ними, смотрите Коммиттинг кода.
Ниже мы покажем, как создать на GitHub pull request, содержащий изменения для Trac ticket #xxxxx. Создав полностью готовый запрос, вы облегчите работу рецензента, а это значит, что ваша работа с большей вероятностью будет внесена в Django.
Вы также можете загрузить традиционный патч в Trac, но это менее практично для обзоров.
Установка Git¶
Django использует Git для контроля исходных текстов. Вы можете download Git, но часто проще установить его с помощью менеджера пакетов вашей операционной системы.
Django Git repository размещен на GitHub, и рекомендуется также работать с помощью GitHub.
После установки Git первое, что вы должны сделать, это настроить свое имя и электронную почту:
$ git config --global user.name "Your Real Name"
$ git config --global user.email "you@email.com"
Обратите внимание, что user.name
должно быть вашим настоящим именем, а не ником на GitHub. GitHub должен знать email, который вы используете в поле user.email
, поскольку он будет использоваться для привязки ваших коммитов к вашей учетной записи GitHub.
Настройка локального репозитория¶
После создания учетной записи GitHub с ником «GitHub_nick» и forked Django’s repository, создайте локальную копию вашего форка:
git clone https://github.com/GitHub_nick/django.git
Это создаст новый каталог «django», содержащий клон вашего репозитория GitHub. Остальные команды git на этой странице должны быть запущены в клонированном каталоге, поэтому переключитесь на него сейчас:
cd django
Ваш репозиторий GitHub будет называться в Git «origin».
Вы также должны настроить django/django
как «upstream» remote (то есть сообщить git, что репозиторий эталонного Django является источником вашего форка):
git remote add upstream git@github.com:django/django.git
git fetch upstream
Аналогичным образом можно добавить другие пульты, например:
git remote add akaariai git@github.com:akaariai/django.git
Работа над билетом¶
При работе над тикетом создайте новую ветку для работы и основывайте эту работу на upstream/master:
git checkout -b ticket_xxxxx upstream/master
Флаг -b создает для вас новую ветку локально. Не стесняйтесь создавать новые ветви даже для самых незначительных вещей - они для этого и существуют.
Если бы вместо этого вы работали над исправлением в ветке 1.4, вы бы сделали:
git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
Предположим, что работа ведется на ветке ticket_xxxxx. Внесите некоторые изменения и зафиксируйте их:
git commit
При написании сообщения о фиксации следуйте commit message guidelines, чтобы облегчить работу коммиттера. Если вы не владеете английским языком, постарайтесь хотя бы точно описать, что делает коммит.
Если вам нужно выполнить дополнительную работу над вашей веткой, делайте коммит так часто, как это необходимо:
git commit -m 'Added two more tests for edge cases'
Издательская деятельность¶
Вы можете опубликовать свою работу на GitHub, просто сделав следующее:
git push origin ticket_xxxxx
Когда вы зайдете на свою страницу GitHub, вы заметите, что была создана новая ветка.
Если вы работаете над тикетом Trac, вам следует указать в тикете, что ваша работа доступна из ветки ticket_xxxxx вашего репозитория на GitHub. Включите ссылку на вашу ветку.
Обратите внимание, что в языке Git вышеупомянутая ветка называется «ветка темы». Вы можете свободно переписывать историю этой ветки, используя, например, git rebase
. Другие люди не должны основывать свою работу на такой ветке, потому что их клон будет поврежден, когда вы будете редактировать коммиты.
Существуют также «публичные ветки». Это ветки, которые должны форкать другие люди, поэтому история этих веток никогда не должна меняться. Хорошими примерами публичных веток являются ветки master
и stable/A.B.x
в репозитории django/django
.
Когда вы считаете, что ваша работа готова к внедрению в Django, вы должны создать запрос на исправление на GitHub. Хорошая заявка означает:
- коммитов с одним логическим изменением в каждом, следующим за coding style,
- хорошо сформированные сообщения для каждого коммита: итоговая строка и затем абзацы, обернутые в 72 символа - см. committing guidelines для более подробной информации,
- документация и тесты, если необходимо - на самом деле тесты нужны всегда, за исключением изменений в документации.
Набор тестов должен пройти, а документация должна собираться без предупреждений.
После того, как вы создали свой pull request, вы должны добавить комментарий в соответствующий тикет Trac, объясняющий, что вы сделали. В частности, вам следует указать среду, в которой вы проводили тесты, например: «все тесты прошли под SQLite и MySQL».
Pull-запросы на GitHub имеют только два состояния: открытый и закрытый. У коммиттера, который будет заниматься вашим запросом, есть только два варианта: объединить его или закрыть. По этой причине не имеет смысла подавать запрос на исправление, пока код не будет готов к слиянию - или достаточно близок, чтобы коммиттер сам закончил его.
Перераспределение ветвей¶
В приведенном выше примере вы создали два коммита, коммит «Fixed ticket_xxxxx» и коммит «Added two more tests».
Мы не хотим иметь всю историю вашего рабочего процесса в вашем репозитории. Ваш коммит «Добавил еще два теста» будет бесполезным шумом. Вместо этого мы бы предпочли иметь только один коммит, содержащий всю вашу работу.
Чтобы переработать историю вашей ветки, вы можете объединить все коммиты в один с помощью интерактивного rebase:
git rebase -i HEAD~2
HEAD~2 выше - это сокращение для двух последних коммитов. Приведенная выше команда откроет редактор, показывающий эти два коммита с префиксом «pick».
Измените «pick» во второй строке на «squash». Это сохранит первый коммит, а второй коммит будет втиснут в первый. Сохраните и выйдите из редактора. Откроется второе окно редактора, и вы сможете переформулировать сообщение о фиксации, теперь оно включает оба ваших шага.
Вы также можете использовать опцию «edit» в rebase. Так вы можете изменить один коммит, например, исправить опечатку в docstring:
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.
Если ваша тематическая ветка уже опубликована на GitHub, например, если вы вносите незначительные изменения, чтобы учесть рецензию, вам нужно будет принудительно вытолкнуть изменения:
git push -f origin ticket_xxxxx
Обратите внимание, что это перепишет историю ticket_xxxxx - если вы проверите хэши коммитов до и после операции на GitHub, вы заметите, что хэши коммитов больше не совпадают. Это допустимо, поскольку ветка является всего лишь тематической веткой, и никто не должен основывать на ней свою работу.
После изменения восходящего потока¶
Если восходящий поток (django/django
) изменился, вам следует перебазировать свою работу. Для этого используйте:
git fetch upstream
git rebase
Работа автоматически ребайтится с использованием ветки, на которую вы форкнули, в примере с использованием upstream/master
.
Команда rebase временно удаляет все ваши локальные исправления, применяет исправления из восходящего потока, а затем снова применяет ваши локальные исправления в работе.
Если существуют конфликты слияния, вам нужно будет разрешить их, а затем использовать git rebase --continue
. В любой момент вы можете использовать git rebase --abort
для возврата к исходному состоянию.
Обратите внимание, что вы хотите базироваться на upstream, а не сливаться с upstream.
Причина этого в том, что при ребазинге ваши коммиты всегда будут поверх работы апстрима, а не смешаны с изменениями в апстриме. Таким образом, ваша ветка будет содержать только коммиты, относящиеся к её теме, что облегчает сквошинг.
После рассмотрения¶
Необычно получить любой нетривиальный объем кода в ядро без изменений, запрошенных рецензентами. В этом случае часто хорошей идеей будет добавить изменения в виде одного инкрементного коммита к вашей работе. Это позволит рецензенту легко проверить, какие изменения вы внесли.
В этом случае внесите изменения, требуемые рецензентом. Выполняйте коммит так часто, как это необходимо. Перед публикацией изменений перебазируйте свою работу. Если вы добавили два коммита, вы выполните:
git rebase -i HEAD~2
Втисните второй коммит в первый. Напишите сообщение о фиксации следующего содержания:
Made changes asked in review by <reviewer>
- Fixed whitespace errors in foobar
- Reworded the docstring of bar()
Наконец, верните свою работу в репозиторий GitHub. Поскольку вы не трогали публичные коммиты во время ребазинга, вам не нужно принудительно проталкивать:
git push origin ticket_xxxxx
Теперь ваш запрос на исправление должен содержать и новый коммит.
Обратите внимание, что при фиксации кода коммиттер, скорее всего, втиснет коммит обзора в предыдущий коммит.
Работа над патчем¶
Один из способов, которым разработчики могут внести свой вклад в развитие Django - это рецензирование патчей. Эти исправления обычно существуют в виде запросов на GitHub и могут быть легко интегрированы в ваш локальный репозиторий:
git checkout -b pull_xxxxx upstream/master
curl https://github.com/django/django/pull/xxxxx.patch | git am
Это создаст новую ветку, а затем применит к ней изменения из запроса на исправление. На этом этапе вы можете запустить тесты или сделать все остальное, что необходимо для исследования качества патча.
Более подробную информацию о работе с запросами на вытягивание см. в guidelines for committers.
Резюме¶
- Работайте на GitHub, если можете.
- Объявите о своей работе в тикете Trac, указав ссылку на свою ветку GitHub.
- Когда у вас будет что-то готово, сделайте запрос на выгрузку.
- Делайте свои запросы на исправление ошибок как можно лучше.
- При внесении исправлений в свою работу используйте
git rebase -i
для сглаживания коммитов. - Если восходящий поток изменился, сделайте
git fetch upstream; git rebase
.