Git: сохранение многих ветвей темы на часто движущейся базе

В моем ежедневном рабочем процессе git у меня много ветвей темы, например:

              o--o--o (t2)
             /
         o--o (t1)
        /
 o--o--o (master)
        \
         o--o--o (t3)

Когда я тянусь вверх по течению,

              o--o--o (t2)
             /
         o--o (t1)
        /
 o--o--o--n--n--n (master)
        \
         o--o--o (t3)

Я хочу переустановить все мои ветки темы поверх нового мастера:

                        o'--o'--o' (t2)
                       /
                  o'--o' (t1)
                 /
 o--o--o--n--n--n (master)
                 \
                  o'--o'--o' (t3)

В настоящее время я делаю это вручную, используя git rebase --onto. В этом случае весь процесс обновления будет:

$ git checkout master
$ git pull
$ git rebase master t1
$ git rebase --onto t1 t2~3 t2
$ git rebase master t3

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

Зависимости между ветвями темы в моем случае являются чисто древовидными: ни одна ветка не зависит от более чем одной другой ветки. (Я должен в конечном итоге воссоздать зависимые исправления в определенном порядке, поэтому я выбираю этот порядок априори.)

Существуют ли какие-либо инструменты, которые могут помочь мне управлять этим документооборотом? Я видел TopGit, но, похоже, он очень сильно привязан к рабочему процессу на основе электронной почты tg patch, что не имеет для меня отношения.

Ответ 1

Почти такой же вопрос задавался в списке рассылки git: Rebasing Несколько ветвей сразу... Связанный ответ имеет прикрепленный скрипт perl, который генерирует команды, которые вам понадобятся.

Если вы хотите, чтобы этот скрипт был быстрым и не пропустил его на пальцах ног, также подумайте о том, чтобы использовать git-new-workdir для создания рабочей копии только для автоматического перезагрузки.

Если вы снова и снова разрешаете одни и те же конфликты, подумайте о включении git rerere.

Сказав все это, вот альтернативный рецепт:

# Construct a placeholder commit that has all topics as parent.
HEADS="$(git for-each-ref refs/heads/\*)" &&
MAGIC_COMMIT=$(echo "Magic Octopus"$'\n\n'"$HEADS" |
  git commit-tree \
    $(git merge-base $(echo "$HEADS" | sed 's/ .*//' ))^{tree} \
    $(echo "$HEADS" | sed 's/ .*//;s/^/-p /')) &&
git update-ref refs/hidden/all $MAGIC_COMMIT

# Rebase the whole lot at once.
git rebase --preserve-merges master refs/hidden/all

# Resolve conflicts and all that jazz.

# Update topic refs from the rebased placeholder.
PARENT=
echo "$HEADS" |
while read HASH TYPE REF
do
  let ++PARENT
  git update-ref -m 'Mass rebase' "$REF" refs/hidden/all^$PARENT "$HASH"
done

Ответ 2

Не переустанавливайте. Начните свои функции с общей точки. В конечном итоге слияния - это еще меньше.

Это то, что мы делаем:

http://dymitruk.com/blog/2012/02/05/branch-per-feature/