Git: Как перебазировать сразу несколько веток (с одним базовым коммитом)? - PullRequest
56 голосов
/ 15 мая 2009

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

Мой вопрос: есть ли способ для меня, чтобы внести новые изменения в мой мастер, а затем перенести ВСЕ мои ветки тем на это сразу?

Это ситуация:

        D--E topic1
       /
A--B--C  master
       \
        F--G topic2

И я хочу сделать это с помощью одной команды (H пришёл из апстрима):

               D'--E' topic1
              /
    A--B--C--H  master
              \
               F'--G' topic2

Теперь я знаю, что могу сделать это, переместив topic1 и topic2 на master, и я мог бы даже написать скрипт для автоматизации этого. Но что, если у меня есть несколько других веток, я создаю новые и часто удаляю другие, и я постоянно получаю изменения из основной ветки?

Эта операция (несколько возвратов), выполняемая вручную, утомительна и подвержена ошибкам.

Есть ли более простой способ?

Спасибо!

Ответы [ 3 ]

18 голосов
/ 15 мая 2009

Я вполне уверен, что нет способа автоматически сделать это. Помните, что «git rebase master» также может вернуть вас в оболочку, которая требует разрешения конфликтов слияния, поэтому, если вы хотите написать скрипт для автоматизации всего этого, вам необходимо это учесть.

Вы можете довольно легко отследить, какие ветви нуждаются в обновлении. Хм, для любой ветви, "git rev-list branch..master" будет выводить результат, если ветвь не обновлена ​​по отношению к master (то есть, просто фиксируется поверх). Таким образом, вам нужно перебрать все локальные заголовки, кроме master, чтобы создать отчет (nb "git show-branch" примерно сделает это):

git for-each-ref 'refs/heads/*' | \
  while read rev type ref; do
    branch=$(expr "$ref" : 'refs/heads/\(.*\)' )
    revs=$(git rev-list $rev..master)
    if [ -n "$revs" ]; then
      echo $branch needs update
      git diff --summary --shortstat -M -C -C $rev master
    fi
  done

Так что, если вы чувствуете себя смелым, вы можете заменить этот "git diff" на что-то вроде "git checkout $ branch && git rebase master" (или, может быть, просто "git pull --rebase", если вы настроили это) , Я думаю, что вам нужно будет проверить наличие каталога «.git / rebase-apply» или проверить индекс на наличие необработанных файлов («git ls-files -u»), чтобы проверить, не осталось ли нас в ожидании сделать слияние.

Конечно, если нет конфликтов, тогда это просто ... он производит что-то, что также работает, когда это нелегко, это проблема: p

И это не обязательно относится к тому, что происходит, если одна из ваших веток основана на чем-то другом ... вот почему я упомянул вместо этого использование "git pull --rebase", потому что это будет перебазировать в соответствии с конфигурацией ветки, а не слепо от хозяина. Хотя обнаружение не основано на конфигурации ветви ... может быть, было бы проще всего проверить каждую ветку и выполнить "git pull", и позволить конфигурации ветви обрабатывать все, включая перебазирование или объединение?

8 голосов
/ 14 декабря 2011

Вы всегда можете написать однострочник оболочки следующим образом:

for branch in topic1 topic2 topic3;do git rebase master $branch;done

Поскольку ветки тем, которые вы хотели бы перебазировать, со временем, вероятно, изменятся, это быстрое и быстрое решение: -)

0 голосов
/ 22 сентября 2016

Я превратил это в надежный скрипт, поддерживаемый в моем репозитории git-extensions :

$ git-urebaselocalbr --help
Rebase all / the last committed N local branches (except for the current branch
and master) to the updated upstream head.
Usage: git-urebaselocalbr [--continue|--skip|--abort] [--branches "<branch1> ..."] [N] [-i|--interactive] [options]
...