воскресенье, 26 апреля 2009 г.

Git на практике на примере django

Как пропатчить django под себя и не сломать себе жизнь.

django хороший проект, но очень уж тормозной в плане мелких доделок. Да и не мелких тоже - баги висят по полгода-год, даже с приложенными патчами. Ждать пока великие хранители django снизойдут до рассмотрения ваших низменных потребностей не очень хочется, благо прогресс не стоит на месте и сделать это проще простого.

План таков:

  1. Настроить git
  2. Склонировать django репозиторий
  3. Создать свой branch (ветку), где мы будем прикладывать нужные нам патчи
  4. Собственное прикладывание патчей, вытягивание изменений из других веток, тыренье кода у друзей и соседей
  5. Поддержание всего этого добра в актуальном состоянии
Приступим.

Настройка и клонирование git.

Тут всё просто.


$ git config --global user.email "your@email.ru" 
$ git config --global user.name "Your Name" 
$ git clone git://github.com/django/django.git 

Сначала настраиваем на текушей машинке наши учетные данные, так удобнее потом будет разгребать что мы напатчили, а что из далека приплыло с обновлениями. Потом клонируем django репозиторий с github (мега ресурс, долгих лет жизни ему), при этом в текущей директории будет создана папка django, а в ней появятся файлы из trunk. По состоянию на сегодняшнее число вся история всех веток от начала времен съест у вас 27 MiB трафика.

Создаём свою песочницу.

Теперь построим свою версию django, с блекджеком и шлюхами. Для этого надо всего ничего:


$ git checkout -b dj-patched origin/master

Таким образом мы создали ветку dj-patched из удаленной ветки origin/master (соотвествует svn trunk). Если вы захотите взять за основу какую-то другую ветку то их список можете посмотреть так:


$ git branch -a            
* dj-patched
  master
  origin/0.90-bugfixes
  origin/0.91-bugfixes
  origin/0.95-bugfixes
  origin/0.96-bugfixes
  origin/HEAD
  origin/admin_changelist_refactor
  origin/admin_generic_relations
  origin/attic
  origin/boulder-oracle-sprint
  origin/connection_pooling
  origin/formset_unique_data
  origin/formset_unique_together
  origin/full-history
  origin/generic-auth
  origin/gis
  origin/i18n
  origin/inline_mi
  origin/magic-removal
  origin/master
  origin/modelform_unique_validation
  origin/multi-auth
  origin/multiple-db-support
  origin/multiprocess_tests
  origin/new-admin
  origin/newforms-admin
  origin/onetoone_as_pk
  origin/per-object-permissions
  origin/queryset-refactor
  origin/releases/1.0.X
  origin/schema-evolution
  origin/schema-evolution-ng
  origin/search-api
  origin/sqlalchemy
  origin/unicode

Большинство этих веток либо заброшенное старье, либо эксперименты с кодом. Если вы тёртый калач, который доверяет только стабильным релизам, то советую обратить внимание на ветку origin/releases/1.0.X, мне же, как ярому красноглазику веселее сидеть на trunk.
Звездочкой в листинге выше помечена ветка, на которой мы сейчас находимся (т.е. файлы, которые мы видим по ls).

Делаем всё, что захотим.

Самое время добавить немного блекджека. Для примера возьмем два супер мелких бага, которые будут висеть вечно: #9637 и #6877.


$ ... накладывам патч, правим код ...
$ git commit -a -m "Fix #9637, la la la"
$ ... накладываем другой патч, еще правим код ...
$ git commit -a -m "Fix #6877, la la la"

Идея, думаю, понятна. Поправили проблему, проверили что работает, сделали commit, т.е. зафиксировали это состояние на века. Взялись за следующую проблему и так далее по кругу. Не стоит смешивать в одном комите несколько патчей, так другим будет проще разобраться в ваших наработках, да и вам через некоторое время тоже.

Перед commit можно сделать git status и git diff, чтобы увидеть, что же мы наделали. Если в процессе работы были добавлены новые файлы, то их надо занести в реп командой git add (можно прямо весь каталог указать, если уверены, что все новые файлы которые там есть, вам нужны в репе).

Одним блекджеком сыт не будешь.

Вы думаете вы одни такие, пилите что-то под себя? Таких много, и есть даже те, которым не жалко поделиться. Идем на github и смотрим, кто что выпилил взяв за основу django репозиторий. Для этого у каждого репа есть страничка Networks. Буквально сразу видим ветку wsgi_translators у пользователя teepark. Кликаем, копаемся, и понимаем, что он написал decorator, который любое wsgi приложение превращает в джанговский view. Глаза вспыхивают красным, капает слюна, и нам во что бы то ни стало надо заполучить этот код. Естественно наши тщательно подобранные и ухоженные патчи тоже должны остаться. Поехали.


$ git remote add gh-teepark git://github.com/teepark/django.git (1)
$ git pull gh-teepark wsgi_translators (2)

Быстро да?

  1. Подключили удаленные git репозиторий с адресом git://github.com/teepark/django.git под именем gh-teepark.
  2. Получить обновления из репозитория gh-teerpark, взять его ветку wsgi_translators и влить её в текущую ветку
Замечу, что хотя реп gh-teepark и содержит в себе всю историю django от начала времен, нам не придется закачивать её снова, т.к. git умный и понимает, что она у нас уже есть (это работает благодаря сравнению историй нашей и удаленной, а не сравнению файлов как в rsync) и качает только то, что нам действительно нужно. В итоге эта операция заняла 31.91 KiB трафика. Владельцы GPRS модемов уже любят git :) Таким образом вы можете подключить неограниченное число git веток, при этом не путаясь в патчах и не проклиная всё на свете.

Ухаживаем за нашим детищем.

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


$ git checkout dj-patched (1)
$ git pull (2)
$ git pull gh-teepark wsgi_translators (3)
$ git pull another_repo another_branch
$ ...

Ну тут пояснений много не требуется.

  1. Переключаемся на ветку dj-patched (мало ли, где нас носило)
  2. Получаем обновления из основной django веткой (у нас это origin/master)
  3. Получаем обновления из других втянутых к нам веток, они же тоже не стоят на месте

git сам разрулит большенство проблем с объединением изменений. Если в каком-то коммите django владыки будут трогать код в тех же файлах и в тех же строках, которые затрагивают ваши патчи (например баг наконец-то пофиксили или просто проводят свои ремонтные работы, но по другому поводу), то тогда возникнет конфликт. Вам надо будет заглянуть в файл и самим привести конфликтные места в порядок, обычно это не доставляет больших сложностей, да и случается совсем редко.

среда, 21 января 2009 г.

Django из Git

Пора переходить на лучшее.

Если кому-то надоел ублюдочный SVN, то можно брать Django из ежечасно обновляемого Git:

git clone git://github.com/django/django.git django.git
Или Mercurial:
hg clone http://bitbucket.org/mirror/django/ django.hg