Відстежуйте всі віддалені гілки 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

Я в Google і RTM, але поки що придумав двоярусне місце.


3
Існує ще простіший спосіб відстежити одну віддалену гілку як локальну гілку:git checkout --track origin/branchname
Cerran

Це не зовсім те, про що ви просили, але працює для мене: отримуйте git завершення: github.com/git/git/blob/master/contrib/completion/… . Потім введіть git pull origin і натисніть tab, щоб отримати список віддалених гілок. Потім продовжуйте набирати текст і натисніть return.
Макс Хайбер

Відповіді:


111

Використання bash:

після 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

кредити: Вал Блант, Еліас та Гюго

перед git 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

Ігноруючи неоднозначні застереження щодо перейменування, git, здається, надає перевагу місцевій гілці як слід.


2
Дякуємо за детальну інформацію про попередження про перейменування. Це було корисно.
Пол

1
Дякую Отто, я підозрював, що сценарій буде єдиним рішенням. Ви надали досить простий.
Янсон

1
@Jason, це все ще сьогодні сценарій єдиного рішення?
Крего

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

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

183

Відповідь, яку дав Отто, хороша, але всі створені гілки матимуть "походження /" як початок назви. Якщо ви просто хочете, щоб остання частина (після останнього /) була вашими іменами гілок, використовуйте це:

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

Це також має перевагу, щоб не давати вам попереджень про неоднозначні відмови.


Git не додасть "походження" до локальної назви гілки відстеження.
Адам Дімітрук

14
@adymitruk: Насправді він поводиться точно так, як я сказав для мене на OSX 10.6.4, використовуючи git 1.7.2.2 (остання стабільна стаття цього коментаря). Отто навіть згадує про неоднозначні застереження щодо перейменування - попередження не потрібно було б існувати, якби "походження /" не було частиною кожної назви місцевої гілки. Ось результат 'гіт гілки' після запуску команди Отто: [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/підрядку ми використовуємо маніпуляцію з рядком Баша ${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/^[ ]\+//'); 

І він використовує $()замість застарілих задників .

Як я згадую в іншій старій відповіді , використання git for-each-ref, ймовірно, швидше .
І я використовував би нову git switchкоманду (Git 2.23+) , яка замінює заплутане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 shell, тестований на 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
Це дає мені "фатально: гілка" все, що "не існує" для кожної гілки, яка існує лише на віддаленому і не має відповідної локальної гілки.
Кріс Додд

Я думаю, якщо назва гілки містить / наприклад: особливість / rc-41-bckend, це рішення не працює !!!!
Мохсен Абасі

@VonC Виходячи з відповіді "slm": $ для i в $ (git гілка -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); робити git checkout - відслідковувати $ 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

Якщо ви хочете скористатися powerhell, а ваш пульт називається початком. Тоді це працює.

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

Це було дуже корисно, я в кінцевому підсумку використав невелику варіацію, щоб змусити працювати з моїм git svn clone'dрепо:git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Нейт

Я також зробив невеликі зміни, оскільки мої місцеві відділення вже існують: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

Використовуйте це, і у вас не буде такого попередження, як: перейменувати 'походження / dev' неоднозначно


3

Ось моє рішення команди BASH з посиланням на @tjmcewan:

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

Моя мета - вирішити проблему, що всі створені гілки матимуть "початок /" як початок імені, тому що я перевірив, що $ віддалені змінні все ще включають "походження /":

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

Після тестування BASH @tjmcewan я виявив, що всі відстежувані гілки "назви" без "походження /" на локальному рівні, я не знаю, чому.
Нік Цай

1
Перша команда створює brances, які відстежують "master". Більшість людей може не хотіти цього.
Олексій Осіпов

@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

Від 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 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 гілка -r' (далі 'git remote update' для оновлення інформації про зміни до віддалених) перераховує всі віддалені гілки; 'egrep -vw' використовується для збиття записів, що мають результат HEAD та master.

рядок 3: відстежте названу віддалену гілку, перевіряючи її локально. Простий awk використовується, щоб уникнути "походження /" як суфікса для місцевих гілок.


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.