GitUM

Материал из Etersoft wiki
Перейти к: навигация, поиск

GitUm (Git Upstream Manager) — средство для поддержки работы над ответвлением проекта в git-репозитории.

Общее описание gitum

Представим, что есть проект, имеющий публичный git-репозиторий. Если вы участвуете в его разработке, то иногда передаёте ваши коммиты, и их включают в общее дерево, которое является достаточно стройным. Но иногда бывают задачи, когда к такому проекту у вас имеется много изменений, которые по каким-то причинам у вас не приняты. Тогда вы создаёте свой репозиторий, размещая туда свои добавления. Что происходит, когда вам нужно обновить ваш репозиторий до состояния апстрима? Либо вы делаете merge (при этом ваши изменения остаются где-то далеко в истории репозитория, и постепенно размазываются по merge-коммитам из-за возникающих конфликтов при обновлении), либо обновление выполняется с --rebase (при этом ваши изменения всегда остаются поверх всего кода из апстрима — это очень наглядно и удобно, но из-за rebase теряется история изменений). gitum решает эту проблему, ведя несколько веток с кодом, и осуществляя обновление из upstream-репозитория таким образом, что у вас есть и ветка, где выполнен rebase (ваши коммиты на виду), и ветка, где ведётся история изменений (и апстрима и ваших), и ветка, где ваши изменения доступны в виде отдельных файлов. Таким образом достигается возможность лёгкой синхронизации с upstream, не теряя при этом изменений и не создавая merge-коммитов, которые мы в данной ситуации считаем большим злом. Подобное слежение за апстримом может быть полезно и при сопровождении пакетов в репозиториях дистрибутивов (как известно, многие пакеты в репозиториях обрастают патчами, адаптирующими их к политике дистрибутива, чинящими сборку и пр.).


Устройство репозитория gitum

Gitum имеет 5 рабочих веток:

  1. Ветка rebased с патчами наверху — рабочая ветка, создаётся локально.
  2. Ветка current с непрерывной историей изменений.
  3. Ветка patches с патчами в виде отдельных файлов — каждый коммит это состояние репозитория.
  4. Ветка upstream - копия апстрим-ветки.
  5. Ветка gitum-config с конфигурационным файлом, где содержатся имена 4-х предыдущих веток. Носит всегда название gitum-config. Может отсутствовать - тогда используются имена веток по умолчанию.

Создадим gitum репозиторий

gitum create [ --remote REMOTE ] [ --upstream UPSTREAM ] [ --rebased REBASED ] [ --current MAINLINE ] [ --patches PATCHES ]

Где

  • REMOTE — апстрим репозиторий/ветка (или просто любая локальная ветка — тогда без /), из которой будем тянуть изменения (по умолчанию, origin/master);
  • UPSTREAM — наша копия ветки REMOTE (по умолчанию, upstream);
  • REBASED — ветка с нашими патчами наверху (по умолчанию, rebased);
  • MAINLINE — отображает последовательную историю (по умолчанию, mainline);
  • PATCHES — ветка с нашими патчами в виде отдельных файлов (по умолчанию, patches).

Ветка REMOTE, из которой берутся изменения должна существовать на момент выполнения команды. Ветка UPSTREAM так же должна быть существовать при выполнении команды, в противном случае к указанному названию приводится текущая активная ветка. Три последние локальные ветки создаются автоматически.

Особенно важно, что git-репозиторий должен быть предварительно либо получен с помощью git clone, либо создан с помощью git init.

Например:

gitum create

переименует текущую ветку в upstream, создаст ветки rebased, mainline и patches, а в качестве апстрим ветки задаст origin/master.

Перенесём изменения из апстрим репозитория

gitum merge [ --track ] [--branch BRANCH] [ --continue | -- abort | -- skip ]

В процессе merge могут возникать конфликты слияния. Нужно разрешить очередной конфликт, добавить исправленные файлы командой

git add

и продолжить процесс:

gitum merge --continue

Если же вы передумали делать merge, то можно вернуть изначальное состояние актуальных веток с помощью команды:

gitum merge --abort

Либо пропустить текущий патч и продолжить процесс:

gitum merge --skip

В результате в ветке разработки mainline у нас появятся копии коммитов из удалённой ветки (сохранено описание, авторство и, по возможности,функционал). Так же вы сможете заметить, что история остаётся непрерывной и отсутствие коммитов вида: "Merge remote into local". Так же можно указать вручную с какой веткой проводить слияние, указав вначале:

gitum merge --branch local_branch

или

gitum merge --branch remote1/branch1

Опция --track позволяет сохранить указанную ветку для использования по умолчанию.

Сохраним изменения в gitum репозиторий

После того, как мы изменили ветку rebased (добавили коммиты или изменили старые), надо обновить ветки mainline и patches:

gitum update [ --message MESSAGE ]

Возможны два сценария:

  1. В ветку rebased были добавлены новые коммиты поверх. Тогда команда автоматически перенесёт данные коммиты в gitum.
  2. В ветке rebased были произведены любые другие изменения, кроме случая описанного в (1): изменение коммитов, добавление в середину, удаление коммитов и прочее. Тогда команда добавит результирующий diff между ветками rebased и mainline в gitum и предложит ввести сообщение коммита, если не указан параметр --message.

Посмотрим состояние репозитория

gitum status

что покажет:

  1. Патчи, которые будут добавлены в случае последующего gitum update, если существующие патчи не менялись;
  2. Результирующий дифф изменений ветки rebased, который будет сохранён в виде отдельного коммита, если существующие патчи менялись (с помощью команд git rebase или git commit --amend).

Восстановим исходное состояние рабочей ветки

Если после модификации ветки rebased решено вернуть её в предыдущее состояние, то используется команда

gitum restore [ --commit COMMIT ] [ --full]

которая так же принимает опцию --commit из ветки patches (по умолчанию — HEAD из patches).

В случае потери всех веток используется опция --full.

Склонируем удалённый gitum репозиторий

gitum clone GITUM-REPO [DIR]

что склонирует репозиторий по адресу GITUM-REPO в директорию DIR. Если DIR не указана, то будет использовано значение по умолчанию, как это делает git clone.

Вытянем изменения из удалённого gitum репозитория

gitum pull [ --remote REMOTE ] [ --track ] [ --resolved | --skip | --abort ]

при этом наши локальные патчи расположатся поверх новых изменений — история сохраняется.

Если в процессе наложения возникли проблемы, то нужно их исправить, сделать git add и дать команду

gitum pull --resolved

или пропустить текущий патч (--skip), или прервать процесс и вернуть первоначальное состояние репозитория с помощью

gitum pull --abort.

Опция --track позволяет сохранить указанный удалённый репозиторий для использования по умолчанию.

Сохраним изменения в удалённый gitum репозиторий

gitum push [ --remote REMOTE ] [ --track ]

Опция --track позволяет сохранить указанный удалённый репозиторий для использования по умолчанию.


Удалим gitum файлы из репозитория

gitum remove [ --full | --branches | --configfiles ]

Дополнительно

  • У gitum есть опция --repo ПУТЬ, которая указывает путь до gitum-репозитория. Если опция не указана, то поиск ведётся в текущем каталоге.

Примеры использования

Сюжет 1. Разработчик вносит изменения, создавая новые коммиты.

Разработчик вносит изменения в ветку rebased, делает коммит своих изменений, указывая для них описание.

Для полного внесения изменений в репозиторий достаточно выполнить команду gitum update, которая ничего не будет спрашивать, просто распределит нужным образом новые коммиты, создав необходимое число коммитов в mainline.

Сюжет 2. Мерж с апстримом

Изменения из апстрима вынимаются в виде отдельных коммитов, при этом выполняется git rebase, возможно, выполняющий (возможно, с ручным вмешательством) изменение созданных у нас коммитов.

В результате в mainline должны быть перенесены уложенные поверх наших патчей коммиты апстрима (с их собственным описанием), в rebase все наши патчи расположены поверх новых коммитов из апстрим, а в patches занесены новые версии наших патчей.

PostgreSQL

1) gitum clone  git.eter:/projects/postgresql/postgre-etersoft-9.2.git
2) git remote add postgre-upstream git://git.postgresql.org/git/postgresql.git

Для gitum merge нужно получить remotes-ветки

3) git fetch  postgre-upstream

Проверяем

4) git branch -a
* mainline
  patches
  rebased
  upstream
  remotes/origin/mainline
  remotes/origin/patches
  remotes/origin/upstream
  remotes/postgre-upstream/REL2_0B
  ...
  remotes/postgre-upstream/REL9_2_STABLE
  remotes/postgre-upstream/REL9_3_STABLE
  remotes/postgre-upstream/REL9_4_STABLE
  remotes/postgre-upstream/REL9_5_STABLE
  remotes/postgre-upstream/Release_1_0_3
  remotes/postgre-upstream/WIN32_DEV
  remotes/postgre-upstream/ecpg_big_bison
  remotes/postgre-upstream/master

Обновляем upstream и объединяем его с mainline

5) gitum merge --branch postgre-upstream/REL9_2_STABLE
   *Слово "remotes/" опускаем
   *Команду можно выполнять из любой ветки gitum ( mainline, patches, rebased, upstream )

При конфликте файлов:

6)"gitum merge --continue" - When you have resolved this problem
  "gitum merge --skip"     - If you prefer to skip this patch
 Или
  "gitum merge --abort"    - To check out the original branch and stop rebasing

Обновить до конкретного Тэга или коммита

ВНИМАНИЕ: стоит избегать одинакового названия веток и тегов!
Потому что git всеяден и над чем(веткой или тегом) будет работать не понятно.

1) Тянем информацию и теги

 $ git fetch remote-upstream

2) Находим нужный тег ( коммит ) с релизом

3) Создаём ветку с именем "Release-имя_тега" на базе ветки upstream

 $ git checkout -b Release-REL9_2_13 upstream
 * После успешного выполнения нас автоматически переводит в новую ветку

4) Тянем изменения до коммита помеченного необходимым тегом. В нашем случае это "REL9_2_13"

 $ git pull remote-upstream REL9_2_13

5) Обновляем upstream и mainline

 $ gitum merge --branch Release-REL9_2_13

Замечания

  • Для gitum pull/push задание remote сделано через --remote, хотя в gitum clone и во всём git можно просто писать git push remote — нужно сделать команды максимально похожими на git
  • Нет -f (--force) для gitum push
  • При gitum clone и gitum push может молча что-то долго делать — возможно, не хватает информативности: выполняемые команды и их вывод не видны
  • Опечатка в слове current: gitupstream/gitupstream.py:CURRENT_REBASED = '.git/.curent_rebased'
  • Есть идея записывать версию gitum, которым был создан репозиторий и предупреждать, что очень старый репозиторий, произошли несовместимые изменения? Надо только понять, в какой момент эту версию обновлять.
  • В случае ошибок выпадаем не в тот репозиторий, где были, пользователь в растерянности
  • Я так и не понял, чем закончилась потеря текущего каталога при переключении репозитория. Осталась ли проблема, и когда она.
  • В рамках борьбы с абортами предлагаю заменить --abort на --cancel.
  • gitum merge сравнивает ветку upstream с веткой, переданной ему через параметр --branch. Поэтому если сделать git pull в upstream, то ветка сравнивается сама с собой и gitum говорит о том, что ветка обновлена. Возможно, это не баг, но по этой причине gitum merge работает пока только с remotes-ветками. Тут важно продумать, как сделать, чтобы не надо было указывать ветку через --branch при каждом merge, чтобы она сохранилась изначально при создании репозитория.
  • При использовании репозитория для сборки пакетов в нём появляются дополнительные к mainline ветки, которые надо носить с собой (sisyphus, p7 и т.п.). Нужно продумать, как встроить публикацию и клонирование этих веток. Возможно, где-то регистрировать и сохранять список. Команду добавления хранимой ветки?

Выполнено в 0.7.0-alt1:

  • Должен быть скрипт для тестирования (создание репозитория, веток, выполнение основных команд, проверка появления необходимых файлов)
  • Должен работать просто gitum create (с параметрами по умолчанию)
  • При начальной инициализации требует, чтобы ветка upstream была заранее руками создана — зачем это нужно?
  • Нужен пример создания gitum-репозитория на примере удалённого (с github)
  • При gitum update предлагает ввести описание коммита для mainline (где наследование?!): При update из rebased должны переноситься новые коммиты по отдельности (без вопросов об описании коммита), плюс изменения в репозитории, если есть, с запросом коммита.
  • В ветке patches полное дерево зачем-то ещё есть — можно от него избавится?
  • Просто gitum pull не работает
  • Релизовать поддержку работы не из корня

Исходный код

Ссылки

Почему не merge

Обратная точка зрения:

Заключение

Просьба ко всем, кому интересен данный проект, его попробовать и написать свой отзыв в багу: http://bugs.etersoft.ru/show_bug.cgi?id=7690.

Также можно писать в рассылку devel@lists.etersoft.ru.

Приветствуются любые замечания и пожелания с вашей стороны!