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

$ 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

我用谷歌搜索了一下,但到目前为止都是胡扯。


当前回答

2020年第一季度更新:Mohsen Abasi在评论中提出了一个更简单的替代方案,基于2014年slm的答案:

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

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

正如我在另一个旧答案中提到的,使用git for-each-ref可能更快。 我将使用新的(Git 2.23+) Git switch命令,它取代了令人困惑的Git签出。

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中,用mssysgit1.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

it will only select upstream branches from the remote you specify in the remote variable (it can be 'origin' or whatever name you have set for one of the remotes of your current Git repo). it will extract the name of the branch: origin/a/Branch/Name => a/Branch/Name through the awk expression. it will set the upstream branch through --set-upstream-to (or -u), not --track: The advantage is that, if the branch already exists, it won't fail and it won't change that branch origin, it will only configure the branch.xxx.(remote|merge) setting. branch.aBranchName.remote=origin branch.aBranchName.merge=refs/heads/a/Branch/Name

该命令将为所有远程上游分支创建本地分支,并将它们的远程和合并设置设置为该远程分支。

其他回答

使用bash, 如果你想签出所有分支:

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

需要注意的是,当您获取新的远程跟踪分支时,并不会自动获得它们的本地可编辑副本。

2020年第一季度更新:Mohsen Abasi在评论中提出了一个更简单的替代方案,基于2014年slm的答案:

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

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

正如我在另一个旧答案中提到的,使用git for-each-ref可能更快。 我将使用新的(Git 2.23+) Git switch命令,它取代了令人困惑的Git签出。

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中,用mssysgit1.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

it will only select upstream branches from the remote you specify in the remote variable (it can be 'origin' or whatever name you have set for one of the remotes of your current Git repo). it will extract the name of the branch: origin/a/Branch/Name => a/Branch/Name through the awk expression. it will set the upstream branch through --set-upstream-to (or -u), not --track: The advantage is that, if the branch already exists, it won't fail and it won't change that branch origin, it will only configure the branch.xxx.(remote|merge) setting. branch.aBranchName.remote=origin branch.aBranchName.merge=refs/heads/a/Branch/Name

该命令将为所有远程上游分支创建本地分支,并将它们的远程和合并设置设置为该远程分支。

这里的大多数答案都使git分支-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分支,你可以确认:

$ 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分支-r,使用grep -vE "HEAD|master"过滤输出中的任何HEAD或master分支。为了只得到分支的名称减去源/子字符串,我们使用Bash的字符串操作${var#stringtoremove}。这将从变量$var中删除字符串"stringtoremove"。在本例中,我们从变量$i中删除字符串origin/。

注意:或者你可以使用git checkout -track…要做到这一点:

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

但我并不特别关心这个方法,因为它在执行签出时在分支之间切换。完成后,它将把您留在它创建的最后一个分支上。

参考文献

10.1. 操纵字符串-高级Bash脚本编写指南 3.5 Git分支-远程分支

以下是我的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:

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)的更高版本中使用,会导致 (错误)所有创建的分支跟踪主 (烦恼)所有创建的本地分支名称都以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似乎更喜欢本地分支。