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

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

$ 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

Я искал в Google и RTM, но пока не нашел.


person Janson    schedule 18.12.2008    source источник
comment
Есть еще более простой способ отслеживать отдельную удаленную ветку как локальную: git checkout --track origin/branchname   -  person Cerran    schedule 05.03.2014
comment
Это не совсем то, о чем вы просили, но работает для меня: получить завершение git: github.com/git/git/blob/master/contrib/completion/. Затем введите git pull origin и нажмите tab, чтобы получить список удаленных ветвей. Затем продолжайте вводить и нажмите return.   -  person Max Heiber    schedule 09.11.2016


Ответы (16)


Используя bash:

after git 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

кредиты: Вэл Блан, Элиас и Хьюго

before git 1.9.1

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

  1. (bug) Все созданные ветки для отслеживания мастера
  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

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

person Otto    schedule 19.12.2008
comment
Спасибо за информацию о предупреждениях о ссылках. Это было полезно. - person Paul; 19.12.2008
comment
Спасибо, Отто, я подозревал, что сценарии будут единственным решением. Вы предоставили довольно простой вариант. - person Janson; 20.12.2008
comment
@ Джейсон, это до сих пор единственное решение? - person cregox; 28.02.2012
comment
@Cawas: вам пока придется вручную создавать ветви отслеживания, но git pull имеет переключатель --all, который будет извлекать + объединять все отслеживаемые ветки. - person naught101; 10.07.2012
comment
@ naught101 git pull --all выбирает все ветки, но объединяется только текущая ветка. - person willkil; 03.01.2013
comment
Ну, в моем случае, видимо, не работает. Например. git branch --track origin/master печатает только fatal: Cannot setup tracking information; starting point is not a branch.. Я знаю, что master на данный момент не является существующей веткой по фактическому происхождению, но какое это имеет значение ...? origin/master по-прежнему является действительной ссылкой ... - person Paul S.; 04.11.2013
comment
Первая команда создала локальные ветки, которые все были в начале, а не в наборах изменений, на которые ссылались удаленные ссылки. Remote был получен из svn, что могло быть дополнительным осложнением! - person Robin; 15.01.2014
comment
Чтобы избежать переключения ветвей и удалить начало / префикс: for remote in $(git branch -r) ; do git branch --track $(echo $remote | cut -d '/' -f2) remotes/$remote; done - person Nicolas; 29.04.2014
comment
У меня это не сработало на Git 1.9.1. git branch --track ‹banch_name› создает новую ветку ‹branch_name›, которая отслеживает мастер локальной ветки вместо удаленной ветки, которую мы хотели. Таким образом, этот скрипт создал кучу локальных веток, указывающих на локальный мастер. Я выложу решение ниже. - person Val Blant; 08.05.2014
comment
Я применил этот ответ, но на самом деле ответ tjmcewan кажется лучше. Чтобы отменить этот ответ, я сделал: for BRANCHNAME in $(git branch | grep origin/) ; do git branch -d "${BRANCHNAME}" ; done - person Stéphane Gourichon; 20.10.2014
comment
Это не работает, когда git выводит такие вещи, как origin/HEAD -> origin/development, потому что символ > передается в git checkout. - person Dan Dascalescu; 30.11.2014
comment
Это испортило репозиторий, см. Комментарий Вэла Бланта. - person Tomas Kubes; 07.04.2015
comment
Ответ tjmcewan лучше - person pilavdzice; 10.08.2015
comment
Несомненно, именно поэтому у него больше голосов, чем у этого (включая мой голос), единственная причина, по которой мой указан выше, заключается в том, что это уже был принятый ответ, когда он написал его два года спустя. Вряд ли это повод для того, чтобы проголосовать против меня. - person Otto; 10.08.2015
comment
ОПАСНО - это приведет к невозможности восстановления в вашем репозитории. - person Chris Dodd; 07.04.2016
comment
Как он скремблирует ваш репозиторий? - person Otto; 07.04.2016
comment
Новая команда из git 2.23 и новее git switch позволяет создавать, если не существует. См. Ответ stackoverflow.com/a/60114809/2594742 для получения дополнительной информации. - person AeroX; 07.02.2020

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

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

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

person tjmcewan    schedule 23.06.2010
comment
Git не будет добавлять источник к имени локальной ветки отслеживания. - person Adam Dymitruk; 11.08.2010
comment
@adymitruk: На самом деле он ведет себя точно так, как я сказал для меня в OSX 10.6.4, используя git 1.7.2.2 (последняя стабильная версия на этот комментарий). Отто даже упоминает о неоднозначных предупреждениях о ссылках - предупреждения не должны существовать, если origin / не является частью каждого имени локальной ветки. Вот результат «git branch» после выполнения команды Отто: [master, origin / HEAD, origin / charts, origin / master, origin / production, origin / staging]. И моя команда: [графики, мастер, постановка, постановка]. - person tjmcewan; 20.08.2010
comment
+1 Это как раз то, что мне нужно. Я удивлен, что это еще не было возможности git. Итак, теперь у меня есть все ветки git.git, и я могу посмотреть, что может быть задействовано! - person Philip Oakley; 27.08.2011
comment
+ Изменить: найдено article.gmane.org/gmane.comp.version- control.git / 112575, объясняя почему. - person Philip Oakley; 27.08.2011
comment
Я согласен - это лучшее решение, чем принятый в настоящее время ответ. - person tobias.mcnulty; 10.04.2012
comment
Это не работает, когда git выводит такие вещи, как origin/HEAD -> origin/development, потому что символ > передается в git checkout. - person Dan Dascalescu; 30.11.2014
comment
@DanDascalescu, да, приятель, если вы не используете master в качестве ветки по умолчанию, вам нужно будет настроить ее. master, однако, является подавляющим условием. - person tjmcewan; 01.12.2014
comment
А как насчет grep -v /HEAD вместо grep -v master? Кажется, это отфильтровывает ветку по умолчанию без необходимости настройки - person dashrb; 08.05.2015

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

Пример

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

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

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

$ 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 ....

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

Цикл в основном вызывает команду git branch -r, отфильтровывая любые ветки HEAD или master в выводе с помощью grep -vE "HEAD|master". Чтобы получить имена только ветвей без подстроки origin/, мы используем манипуляции со строками ${var#stringtoremove} в Bash. Это удалит строку "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

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

использованная литература

person slm    schedule 01.12.2014
comment
Отлично работает с git версии 2.3.2 (Apple Git-55) - person AndrewD; 05.05.2015

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

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

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

Как я уже упоминал в другом старом ответе, используя _ 3_ вероятно быстрее.
И я бы использовал новый (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
    

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

person VonC    schedule 09.06.2011
comment
Это приводит к фатальной ошибке: ветка «все» не существует для каждой ветки, которая существует только на удаленном компьютере и не имеет соответствующей локальной ветки. - person Chris Dodd; 07.04.2016
comment
я думаю, что если имя ветки содержит / например: feature / rc-41-bckend, это решение не работает !!!! - person Mohsen Abasi; 10.03.2020
comment
@VonC На основе ответа slm: $ for i in $ (git branch -r | grep -vE HEAD | master | sed 's / ^ [] \ + //'); сделать git checkout --track $ i; Выполнено - person Mohsen Abasi; 10.03.2020
comment
@MohsenAbasi Выглядит хорошо. В своем ответе я упомянул об использовании --set-upstream-to вместо --track. - person VonC; 10.03.2020
comment
@MohsenAbasi Я включил вашу альтернативу в ответ для большей наглядности. Я добавил еще один возможный способ перечислить удаленные ветки и использовать git switch вместо git checkout. Но твоя (очень хорошая) идея осталась. - person VonC; 10.03.2020

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

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

person Dustin    schedule 18.12.2008
comment
Неплохо подмечено. Основной вариант использования, о котором я думаю, - это настройка локальной среды разработки на основе удаленного репозитория git. Поэтому, когда я делаю свой первоначальный клон, я также хочу отслеживать все удаленные ветки, как они есть в то время. - person Janson; 19.12.2008
comment
Удобный git up обновляет все локальные ветки. - person Hugo; 04.09.2014
comment
для объединения двух репозиториев и удаления удаленного - person endolith; 17.07.2020

без скриптов (в пустом каталоге):

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

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


оригинал (на русском языке).

person aleksandr barakin    schedule 20.05.2016
comment
Это самое простое решение, которое сработало у меня на 2.21.0.windows.1. - person Rotsiser Mho; 12.03.2020
comment
Вау, это работает, и это действительно просто. Не могли бы вы подробнее рассказать, как это работает? - person Maxim Ky; 10.02.2021
comment
@MaximKy попробуйте клонировать с параметром --bare и без него. затем сравните содержимое файлов .git/packed-refs в обоих случаях. с этой опцией ветки изначально создаются как локальные. - person aleksandr barakin; 10.02.2021

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

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}
person BigMiner    schedule 24.03.2016
comment
Это было очень полезно, в итоге я использовал небольшую вариацию, чтобы заставить его работать с моим git svn clone'd репозиторием: git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"} - person Nate; 18.09.2018
comment
Я также сделал небольшое изменение, потому что мои локальные ветки уже существуют: git branch -r | %{$_ -replace " origin/"} | %{git branch -u "origin/$_" $_} - person ch271828n; 18.07.2019

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

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

person bruziuz    schedule 21.01.2013

Вот мое решение команды 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
person Nick Tsai    schedule 05.05.2017
comment
После того, как я протестировал BASH @tjmcewan, я обнаружил, что все отслеживаемые ветки имеют имя без origin / на локальном уровне, я не знаю почему. - person Nick Tsai; 05.05.2017
comment
Первая команда создает бренды, которые являются мастером трека. Это не то, что может понадобиться большинству людей. - person Alexei Osipov; 18.12.2017
comment
@AlexeiOsipov Спасибо! - person Nick Tsai; 19.12.2017

Чтобы сделать то же самое, что и tjmcewan answer, но в 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
person Hugo    schedule 04.09.2014

Начиная с git 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

person AeroX    schedule 07.02.2020

Решение VonC можно упростить еще больше, изменив sed (мне не хватает репутации, чтобы прокомментировать его сообщение):

for branch in $(git branch -r | sed 's,[^/]*/,,g'); do git switch $branch; done

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

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

person Peter Whittaker    schedule 18.12.2020
comment
Интересный момент в моем старом ответе 2011 года. Проголосовали. - person VonC; 19.12.2020

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

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

вы можете использовать следующий сценарий, совместимый с 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
person simonair    schedule 26.06.2012

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» для обновления информации об изменениях на удаленный) перечисляются все удаленные ветки; egrep -vw используется для удаления записей, содержащих в результате HEAD и master.

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

person ksvrgh    schedule 15.10.2013

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

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

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

person Jason Chen    schedule 04.09.2018

person    schedule
comment
Мне пришлось добавить | grep -v HEAD в конвейер, чтобы он работал правильно. - person Elias Dorneles; 04.06.2014