Отслеживайте все удаленные Git-ветки как локальные


175

Отслеживание одной удаленной ветви как локальной ветви достаточно просто.

$ git checkout --track -b ${branch_name} origin/${branch_name}

Перетаскивание всех локальных ветвей до удаленного, создание новых удаленных ветвей по мере необходимости также легко.

$ git push --all origin

Я хочу сделать наоборот. Если у меня есть X количество удаленных веток в одном источнике:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Могу ли я создать локальные ветви отслеживания для всех этих удаленных веток без необходимости их создания вручную? Скажите что-то вроде:

$ git checkout --track -b --all origin

Я гуглил и RTMs, но дошел до конца пока.


3
Есть еще более простой способ отследить одну удаленную ветвь как локальную ветвь:git checkout --track origin/branchname
Cerran

Это не совсем то, о чем вы просили, но работает для меня: получите git-дополнения: github.com/git/git/blob/master/contrib/completion/… . Затем введите git pull origin и нажмите tab, чтобы получить список удаленных филиалов. Затем продолжайте печатать и нажмите return.
Макс Хейбер

Ответы:


111

Используя bash:

после мерзавца 1.9.1
for i in `git branch -a | grep remote | grep -v HEAD | grep -v master`; do git branch --track ${i#remotes/origin/} $i; done

Авторы : Вэл Блант, Элиас и Хьюго.

перед мерзавцем 1.9.1

Примечание: следующий код, если он используется в более поздних версиях git (> v1.9.1), вызывает

  1. (ошибка) Все созданные ветки для отслеживания мастера
  2. (раздражение) Все созданные имена локальных веток должны иметь префикс origin/
for remote in `git branch -r `; do git branch --track $remote; done

Обновите ветки, если в локальных ветвях отслеживания нет изменений:

for remote in `git branch -r `; do git checkout $remote ; git pull; done

Игнорируйте неоднозначные предупреждения refname, git, похоже, предпочитает локальную ветку, как и должно.


2
Спасибо за хедз-ап о предупреждениях refname. Это было полезно.
Пол

1
Благодаря Отто, я подозревал, что сценарии будут единственным решением. Вы предоставили довольно простой.
Янсон

1
@ Джейсон, это все еще сегодня сценарий единственное решение?
Cregox

1
@Cawas: вам придется вручную создавать ветви отслеживания, но git pullесть --allпереключатель, который будет извлекать + объединять все отслеживаемые ветви.
naught101

13
Это не работает для меня на Git 1.9.1. "git branch --track <banch_name>" создает новую ветвь <branch_name>, которая отслеживает мастер локальной ветки, а не удаленную ветку, которую мы хотели. Таким образом, этот скрипт создал кучу локальных веток, указывающих на локального мастера. Я выложу решение ниже.
Вэл Блант

183

Ответ, данный Отто, хорош, но все созданные ветви будут иметь «происхождение /» в качестве начала имени. Если вы просто хотите, чтобы последняя часть (после last /) была вашими именами ветвей, используйте это:

for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

Он также имеет то преимущество, что не дает вам никаких предупреждений о неоднозначных ссылках.


Git не добавит «origin» к имени локальной ветви отслеживания.
Адам Димитрук

14
@adymitruk: На самом деле он ведет себя точно так же, как я сказал для меня в OSX 10.6.4, используя git 1.7.2.2 (последняя стабильная версия на этот комментарий). Отто даже упоминает неоднозначные предупреждения refname - предупреждения не должны были бы существовать, если бы «origin /» не было частью имени каждой локальной ветви. Вот вывод «git branch» после выполнения команды Отто: [master, origin / HEAD, origin / charts, origin / master, origin / production, origin / staging]. И моя команда: [схемы, мастер, производство, постановка].
tjmcewan

1
+ Изменить: найдено article.gmane.org/gmane.comp.version-control.git/112575, объясняющее почему.
Филип Окли

8
Я согласен - это лучшее решение, чем то, что в настоящее время является «принятым» ответом.
tobias.mcnulty

2
А grep -v masterкак насчет grep -v /HEAD? Похоже, это отфильтровывает ветку по умолчанию, не требуя настройки
dashrb

22

Большинство ответов здесь чрезмерно усложняют анализ выходных данных git branch -r. Вы можете использовать следующий forцикл, чтобы создать ветви отслеживания для всех веток на пульте, как показано ниже.

пример

Скажем, у меня есть эти удаленные ветви.

$ git branch -r
  origin/HEAD -> origin/master
  origin/development
  origin/integration
  origin/master
  origin/production
  origin/staging

Убедитесь, что мы не отслеживаем ничего, кроме мастера, локально:

$ git branch -l    # or using just git branch
* master

Вы можете использовать этот вкладыш для создания веток отслеживания:

$ for i in $(git branch -r | grep -vE "HEAD|master"); do 
    git branch --track ${i#*/} $i; done
Branch development set up to track remote branch development from origin.
Branch integration set up to track remote branch integration from origin.
Branch production set up to track remote branch production from origin.
Branch staging set up to track remote branch staging from origin.

Теперь подтвердите:

$ git branch
  development
  integration
* master
  production
  staging

Чтобы удалить их:

$ git br -D production development integration staging 
Deleted branch production (was xxxxx).
Deleted branch development (was xxxxx).
Deleted branch integration (was xxxxx).
Deleted branch staging (was xxxxx).

Если вы используете -vvпереключатель, git branchвы можете подтвердить:

$ git br -vv
  development xxxxx [origin/development] commit log msg ....
  integration xxxxx [origin/integration] commit log msg ....
* master      xxxxx [origin/master] commit log msg ....
  production  xxxxx [origin/production] commit log msg ....
  staging     xxxxx [origin/staging] commit log msg ....

Разбивка цикла

Цикл в основном вызывает команду git branch -r, отфильтровывая любые HEAD или главные ветви в выводе, используя grep -vE "HEAD|master". Чтобы получить имена только ветвей минус origin/подстрока, мы используем манипулирование строк Bash ${var#stringtoremove}. Это удалит строку «stringtoremove» из переменной $var. В нашем случае мы удаляем строку origin/из переменной $i.

ПРИМЕЧАНИЕ. В качестве альтернативы вы также можете использовать git checkout --track ...это:

$ for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do 
    git checkout --track $i; done

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

Ссылки


1
Отлично работает с git версии 2.3.2 (Apple Git-55)
AndrewD

22

Обновление Q1 2020: Мохсен Абаси предлагает в комментариях , на основе 2014 сого «ы ответа , простой альтернативе:

for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); 

И он использует $()вместо устаревших backticks .

Как я уже упоминал в другом старом ответе , использование git for-each-ref, вероятно, быстрее .
И я бы использовал новую (Git 2.23+) git switchкоманду , которая заменяет запутаннуюgit checkout .

for i in $(git for-each-ref --format=%(refname:short) \
  --no-merged=origin/HEAD refs/remotes/origin); do \
    git switch --track $i; \
done

Таким образом, нет grepнеобходимости.


Старый (2011) оригинальный ответ:

Вот мой однострочный текст, который я использую (в оболочке bash, протестирован с msysgit1.7.4):

Для копирования-вставки:

remote=origin ; for brname in `git branch -r | grep $remote | grep -v master | grep -v HEAD | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream-to $remote/$brname $brname; done

Для большей читабельности:

remote=origin ; // put here the name of the remote you want
for brname in `
    git branch -r | grep $remote | grep -v master | grep -v HEAD 
    | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'
`; do 
    git branch --set-upstream-to $remote/$brname $brname; 
done
  • он будет выбирать только восходящие ветви с пульта, который вы указали в remoteпеременной (это может быть ' origin' или любое другое имя, которое вы указали для одного из пультов вашего текущего репозитория Git).
  • это извлечет название ветви: origin/a/Branch/Name => a/Branch/Nameчерез awkвыражение.
  • он будет устанавливать восходящую ветвь через --set-upstream-to(или -u) , а не --track:
    Преимущество состоит в том, что, если ветвь уже существует, она не выйдет из строя и не изменит источник этой ветки, она только настроит branch.xxx.(remote|merge)параметр.

    branch.aBranchName.remote=origin
    branch.aBranchName.merge=refs/heads/a/Branch/Name
    

Эта команда создаст локальные ветви для всех удаленных вышестоящих ветвей и установит их удаленные ветви и настройки слияния для этой удаленной ветви.


5
Это дает мне «роковую: ветвь« все, что не существует »» для каждой ветки, которая существует только на удаленном компьютере и не имеет соответствующей локальной ветки.
Крис Додд

я думаю, что если имя ветви содержит / например: feature / rc-41-bckend, это решение не работает !!!!
Мохсен Абаси

@VonC Основано на ответе «slm»: $ для i в $ (git branch -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); сделать git checkout --track $ i; сделано
Мохсен Абаси

@MohsenAbasi выглядит хорошо. В своем ответе я упомянул использование --set-upstream-toвместо --trackхотя.
VonC

@MohsenAbasi Я включил вашу альтернативу в ответ для большей наглядности. Я добавил еще один возможный способ перечисления удаленных веток и использования git switchвместо git checkout. Но ваша (очень хорошая) идея остается.
VonC

14

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

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


2
Неплохо подмечено. Основной вариант использования, о котором я думаю, - это настройка локальной среды разработки на основе удаленного репозитория git. Поэтому, когда я делаю свое первоначальное клонирование, я также хочу отслеживать все удаленные ветви, как они есть в то время.
Янсон

1
Удобный git upобновляет все местные филиалы.
Хьюго

для объединения двух сделок РЕПО и удаление пульта
эндолиты


9

без каких-либо сценариев (в пустой директории):

$ git clone --bare repo_url .git
$ git config core.bare false
$ git checkout

после этого все удаленные ветви будут рассматриваться как локальные.


оригинал .


На сегодняшний день это самое простое решение, и оно работало для меня на 2.21.0.windows.1
Rotsiser Mho

7

Если вы хотите использовать powershell и ваш пульт называется origin. Тогда это работает.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}

Это было супер полезно, я в конечном итоге , используя небольшое изменение , чтобы заставить его работать с моей git svn clone'dрепо:git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate

Я также внес небольшие изменения, потому что мои местные филиалы уже существуют:git branch -r | %{$_ -replace " origin/"} | %{git branch -u "origin/$_" $_}
ch271828n

3
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do  git branch --track ${branch##*/} $branch; done

Используйте это, и у вас не будет такого предупреждения, как: refname 'origin / dev' является неоднозначным


3

Вот мое решение команды BASH, ссылающейся на @tjmcewan:

for remote in `git branch -r | grep -v /HEAD `; do git branch --track ${remote/"origin/"/""}; done

Моя цель состоит в том, чтобы решить проблему, заключающуюся в том, что все созданные ветки будут иметь «origin /» в качестве начала имени, потому что я проверял, что переменные $ remote по-прежнему включают «origin /»:

for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done

После того, как я протестировал BASH @tjmcewan, я обнаружил, что все отслеживаемые ветки 'name без' origin / 'на локальном, я не знаю почему.
Ник Цай

1
Первая команда создает отряды, которые отслеживают «мастера». Это не то, что может хотеть большинство людей.
Алексей Осипов

@AlexeiOsipov Спасибо!
Ник Цай

2

Чтобы сделать то же самое, что и ответ tjmcewan, но в Windows, вызовите это из командного файла :

for /f "delims=" %%r in ('git branch -r ^| grep -v master') do git checkout --track %%r

Или это из командной строки :

for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r

1

Начиная с версии 2.23:

for branch in `git branch -r | grep origin/`; do git switch -t -C ${branch#origin/} $branch; git pull; done

-CФлаг git switchсоздает или перезагружается , если он уже существует.

git switch документация


0

Если у вас уже есть несколько проверенных веток, и вы хотите

  • проверить все оставшиеся ветви с пульта
  • убедитесь, что все локальные ветви отслеживают удаленные ветви

Вы можете использовать следующий bash- и zsh-совместимый скрипт:

git branch -r | while read b; do if git branch | grep -q " ${b##*/}$"; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done

0
for rembranch in `git remote update 2>&1 > /dev/null ; git branch -r|egrep -wv "HEAD|master"`
do 
    git checkout --track -b `echo $rembranch|awk -F\/ '{print $2}'` $rembranch; 
done

Объяснение:

строка 1: «git branch -r» (за которой следует «git remote update» для обновления информации об изменениях в remote) перечисляет все удаленные ветви; 'egrep -vw' используется, чтобы выбить записи, имеющие HEAD и master в результате.

строка 3: отслеживание названной удаленной ветви при локальной проверке. Простой awk используется, чтобы избежать «origin /» как суффикса для локальных веток.


0

Используя bash, если вы хотите оформить заказ во всех филиалах:

for remote in `git branch -r`; do git checkout $(echo $remote | cut -d'/' -f 2); done

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.