Работа с Git и GitHub

Этот раздел объясняет, как сообщество может вносить код в Django с помощью запросов на исправление. Если вас интересует, как mergers их обрабатывает, смотрите Коммиттинг кода.

Ниже мы покажем, как создать на 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 https://github.com/django/django.git
git fetch upstream

Аналогичным образом можно добавить, например, другие пульты:

git remote add akaariai https://github.com/akaariai/django.git

Работа над билетом

При работе над тикетом создайте новую ветку для работы и основывайте ее на upstream/main:

git checkout -b ticket_xxxxx upstream/main

Флаг -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. Другие люди не должны основывать свою работу на такой ветке, потому что их клон будет поврежден, когда вы будете редактировать коммиты.

Существуют также «публичные ветки». Это ветки, которые должны форкать другие люди, поэтому история этих веток никогда не должна меняться. Хорошими примерами публичных веток являются ветки main и stable/A.B.x в репозитории django/django

Когда вы считаете, что ваша работа готова к внедрению в Django, вы должны создать запрос на исправление на GitHub. Хорошая заявка означает:

  • коммитов с одним логическим изменением в каждом, следующим за coding style,
  • хорошо сформированные сообщения для каждого коммита: итоговая строка и затем абзацы, обернутые в 72 символа - см. committing guidelines для более подробной информации,
  • документация и тесты, если необходимо - на самом деле тесты нужны всегда, за исключением изменений в документации.

Набор тестов должен пройти, а документация должна собираться без предупреждений.

После того, как вы создали свой pull request, вы должны добавить комментарий в соответствующий тикет Trac, объясняющий, что вы сделали. В частности, вам следует указать среду, в которой вы проводили тесты, например: «все тесты прошли под SQLite и MySQL».

Pull request на GitHub имеет только два состояния: открытый и закрытый. У слиятеля, который будет заниматься вашим запросом, есть только два варианта: объединить его или закрыть. По этой причине не имеет смысла подавать запрос на исправление, пока код не будет готов к слиянию - или достаточно близок для того, чтобы объединение само его завершило.

Перераспределение ветвей

В приведенном выше примере вы создали два коммита, коммит «Fixed ticket_xxxxx» и коммит «Added two more tests».

Мы не хотим иметь всю историю вашего рабочего процесса в вашем репозитории. Ваш коммит «Добавил еще два теста» будет бесполезным шумом. Вместо этого мы бы предпочли иметь только один коммит, содержащий всю вашу работу.

Чтобы переработать историю ветки, можно объединить все коммиты в один с помощью интерактивного rebase:

git rebase -i HEAD~2

HEAD~2 выше - это сокращение для двух последних коммитов. Приведенная выше команда откроет редактор, показывающий эти два коммита с префиксом «pick».

Измените «pick» во второй строке на «squash». Это сохранит первый коммит, а второй коммит будет втиснут в первый. Сохраните и выйдите из редактора. Откроется второе окно редактора, и вы сможете переформулировать сообщение о фиксации, теперь оно включает оба ваших шага.

Вы также можете использовать опцию «edit» в rebase. Таким образом, вы можете изменить один коммит, например, исправить опечатку в строке документации:

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/main

Работа автоматически ребайтится с использованием ветки, на которую вы форкнули, в примере с использованием upstream/main

Команда 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. Поскольку в процессе ребазинга вы не трогали публичные коммиты, принудительный push не требуется:

git push origin ticket_xxxxx

Теперь ваш запрос на исправление должен содержать и новый коммит.

Обратите внимание, что слияние, скорее всего, приведет к слиянию коммита обзора с предыдущим коммитом при фиксации кода.

Работа над патчем

Одним из способов, с помощью которого разработчики могут внести свой вклад в развитие Django, является рецензирование патчей. Эти патчи обычно существуют на GitHub в виде pull request’ов и могут быть легко интегрированы в ваш локальный репозиторий:

git checkout -b pull_xxxxx upstream/main
curl -L https://github.com/django/django/pull/xxxxx.patch | git am

Это создаст новую ветку, а затем применит к ней изменения из запроса на исправление. На этом этапе вы можете запустить тесты или сделать все остальное, что необходимо для исследования качества патча.

Более подробную информацию о работе с запросами на вытягивание смотрите в guidelines for mergers.

Краткое описание

  • Работайте на GitHub, если можете.
  • Объявите о своей работе в тикете Trac, указав ссылку на свою ветку GitHub.
  • Когда у вас будет что-то готово, сделайте запрос на выгрузку.
  • Делайте свои запросы на исправление ошибок как можно лучше.
  • При внесении исправлений в свою работу используйте git rebase -i для сглаживания коммитов.
  • Если восходящий поток изменился, сделайте git fetch upstream; git rebase.
Вернуться на верх