git/MergingBranches

Материал из ALT Linux Wiki
Merge-arrow.svg
Необходимо перенести содержимое этой статьи в статью Руководство по gear
Вы можете помочь проекту, объединив их.


Хранение патчей в отдельных бранчах git-репозитория

Предисловие

Наш mutt1.5 это такой mutt2ng-new с большим количеством «левых» патчей. Из-за такого количества каждое обновление версии превращается в изощрённую пытку для мантейнера. Посмотрим, как git может помочь решить подобные проблемы.

Общий мёрж в master

Посмотрим на kernel-image. Там каждый патч живёт в отдельном бранче, перед релизом всё мержится в master. Примерно так:

master
          *  merge-C
         /|
        / *  merge-B
       / /|
      / / *  merge-A
     / / /|
    / / / *  merge-upstream
   / / / /|
  * | | | |  patchC
  | * | | |  patchB
  | | * | |  patchA
   \ \ \| |
    +-+-* |  upstream
        | |

По каждому патчу конфликт разруливается сначала в patchX, потом в merge-X. При обновлении версии upstream и/или patchX приходится делать маленький закат солнца вручную с повторным разруливаением всех конфликтов. Это не ядро и патчи имеют обыкновение пересекаться во множестве мест.

Последовательный мёрж бранчей

Есть второй способ, который применяет voins (например, см. его stklos.git и WindowMaker.git). upstream мержится в patchA, patchA в patchB и так далее. При этом конфликты разруливаются практически только один раз при мерже patchN-1 в patchN:

master
 *
 |\
 | * patchC
 | |\
 | | * patchB
 | | |\
 | | | * patchA
 | | | |\
 | | | | * upstream
 | | | | |

Что делать при обновлении upstream и/или patchX?

1. upstream

patchA <- upstream
patchB <- patchA
…
master <- patchZ

2. patchX

branch patchX-tmp upstream
накладываем новый patchX в patchX-tmp
patchX-tmp <- patch(X-1)
patchX <- patchX-tmp
branch -d patchX-tmp
patch(X+1) <- patchX
…
master <- patchZ

3. patchX и upstream

До patch(X-1) поступаем аналогично 1., потом аналогично 2.

Автоматизация процесса последовательного мёржа

gear-merge

Автоматизировать процесс можно с помощью утилиты gear-merge. Утилита довольно простая. Краткий синтаксис правил описан в заголовке (vim /usr/bin/gear-merge), опции описаны в man-странице.

Вот так выглядит файл правил для мёржа на примере inn.git:

% cat .gear/merge
merge: upstream patches/debian/0001-libdb-4.4
merge: patches/debian/0001-libdb-4.4 patches/alt/001-cdb
merge: patches/alt/001-cdb patches/alt/002-db4
merge: patches/alt/002-db4 patches/alt/003-docs
merge: patches/alt/003-docs patches/alt/004-gdbm
merge: patches/alt/004-gdbm patches/alt/005-pie
merge: patches/alt/005-pie patches/alt/006-2.4.2-alt
merge: patches/alt/006-2.4.2-alt patches/alt/007-krb5
merge: patches/alt/007-krb5 patches/alt/008-Makefile
merge: patches/alt/008-Makefile master

topgit

Также при такой схеме работы с ветками-патчами разработчику поможет довольно широко известная утилита topgit. О её возможностях см. README (upstream).

Схема с последовательным прикладыванием патчей

Из примера выше вместо:

   git branch patchA upstream

для создания ветки патча надо было бы сделать:

   tg create patchA upstream

или (тот же эффект):

   git checkout upstream
   tg create patchA
   # теперь patchA is checked out

После этого будет предложено внести описание патча в .topmsg (что в принципе полезно).

И так с другими ветками, скажем:

   tg create patchB [patchA]
   ...
   tg create master [patchZ]

Работать с ветками как обычно в Git.

Когда какая-нибудь ветка подрастает (добавились коммиты), у topgit есть команда tg update, чтобы автоматически сделать необходимые merges (см. описание в README). Также есть другие полезные команды для работы.

Принципы topgit

В topgit формально сохраняется информация о зависимостях веток-патчей друг от друга. Работа команд опирается на эту информацию.

Но сама по себе запись зависимостей в известном формате полезна, потому что на основе неё можно автоматизировать обработку веток-бранчей так, как задумано их создателем.

Например, я подумываю об инструменте для экспорта репозитория topgit в кучку репозиториев darcs, где каждый репозиторий-ветка будет подмножеством зависимых репозиториев; в общем случае задача транслировать историю Git с ветками в darcs так, чтобы отношение быть подмножеством было хорошим, кажется не очень простой.

Схема с общим merge-м патчей

Схема с общим merge-м патчей (как описано ещё ближе к началу этой страницы) тоже возможна в topgit:

   tg create patchA upstream
   tg create patchB upstream
   ...
   tg create patchZ upstream
   tg create master upsteram patchA patchB ... patchZ

Ссылки