跟踪所有远程git分支作为本地分支


173

将单个远程分支跟踪为本地分支非常简单。

$ 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 2014年

这不是您真正想要的,但是对我有用:获得git 补全github.com/git/git/blob/master/contrib/completion/…。然后键入git pull origin 并点击tab,以获取远程分支的列表。然后继续输入并点击return
Max Heiber,

Answers:


110

使用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

学分: Val Blant,elias和Hugo

在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

忽略模糊的refname警告,git似乎更喜欢本地分支。


2
感谢您对refname警告的注意。那很有帮助。
保罗

1
感谢Otto,我怀疑脚本将是唯一的解决方案。您提供了一个非常简单的方法。
詹森,

1
@Jason仍然是今天编写脚本的唯一解决方案吗?
cregox

1
@Cawas:直到必须手动创建跟踪分支,但git pull仍有一个--all开关,它将获取并合并所有跟踪的分支。
naught101

13
这对我在Git 1.9.1上不起作用。“ git branch --track <banch_name>”创建一个新的分支<branch_name>,该分支跟踪本地分支主机,而不是我们想要的远程分支。因此,此脚本创建了一堆本地分支,所有分支均指向本地主节点。我将在下面发布解决方案。
Val Blant 2014年

183

Otto给出的答案很好,但是所有创建的分支将以“ origin /”作为名称的开头。如果您只希望最后一部分(在最后一个/之后)成为您产生的分支名称,请使用以下命令:

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(此评论中最新的版本)。Otto甚至提到了模糊的refname警告-如果“ origin /”不是每个本地分支名称的一部分,则这些警告就不需要存在。这是运行Otto命令后的“ git branch”输出:[master,origin / HEAD,origin / chart,origin / master,origin / production,origin / staging]。我的命令是:[图表,母版,制作,暂存]。
tjmcewan


8
我同意-这是比当前“可接受”答案更好的解决方案。
tobias.mcnulty 2012年

2
相反grep -v master,怎么样grep -v /HEAD?这似乎可以过滤掉默认分支,而无需自定义
dashrb 2015年

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

for循环的细分

循环基本上会调用该命令git branch -r,并使用过滤掉输出中的任何HEAD或master分支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

2020年第一季度更新:基于2014 slm回答Mohsen Abasi 在评论中提出了更简单的选择:

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

它使用$()而不是过时的反引号

正如我在提到另一个老答案,使用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 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
对于只有远程存在且没有相应本地分支的每个分支,这给了我“致命的分支:任何分支都不存在”。
克里斯·多德

我认为如果分支名称包含/例如:feature / rc-41-bckend,则此解决方案不起作用!!!
Mohsen Abasi

@VonC根据“ slm”的答案:$ for i in $(git branch -r | grep -vE“ HEAD | master” | sed's / ^ [] \ + //'); 做git checkout --track $ i; 完成
Mohsen Abasi

@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/$_" $_}
ch271828n19年

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

这是@tjmcewan引用的BASH命令解决方案:

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

在测试@tjmcewan的BASH之后,我发现所有被跟踪的分支的名称在本地都没有“ origin /”,我不知道为什么。
蔡仔

1
第一个命令创建跟踪“ master”的brance。那不是大多数人想要的东西。
Alexei Osipov

@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 branch -r”(后跟“ git remote update”以更新有关更改到远程的信息)列出了所有远程分支;'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

重要的是要注意,当您进行提取以关闭新的远程跟踪分支时,您不会自动拥有它们的本地可编辑副本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.