将所有远程 Git 分支作为本地分支进行跟踪

发布于 2024-07-10 18:10:13 字数 692 浏览 6 评论 0原文

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

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

我已经用谷歌搜索并阅读了手册,但到目前为止还没有找到答案。

Tracking a single remote branch as a local branch is straightforward enough.

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

Pushing all local branches up to the remote, creating new remote branches as needed is also easy.

git push --all origin

I want to do the reverse. If I have X number of remote branches at a single source:

git branch -r

Output:

branch1
branch2
branch3
.
.
.

Can I create local tracking branches for all those remote branches without needed to manually create each one? Say something like:

git checkout --track -b --all origin

I've googled and read the manuals, but have come up bunk thus far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

挽袖吟 2024-07-17 18:10:14

VonC 的解决方案可以进一步简化:更改 sed (我缺乏直接评论他的帖子的代表点):

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

通过替换所有内容直到最后一个斜杠都不是斜杠,剩余的分支名称适合本地使用; 重复切换到同一个分支并不是一个错误(它可能效率低下,但它可能比在管道中使用 grep 更有效:->)。

switch 命令足够智能,可以根据需要跟踪每个远程分支。

VonC's solution can be simplified even further by changing the sed (I lack the rep points to comment directly on his post):

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

By replacing everything that isn't a slash up to the final slash, the remaining branch name is suitable for local use; repeatedly switching to the same branch isn't an error (it may be inefficient, but it may be more efficient than having a grep in the pipe :->).

The switch command is smart enough to track each remote branch as necessary.

千纸鹤带着心事 2024-07-17 18:10:14

使用重击,
如果您想签出所有分支:

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

请务必注意,当您执行获取新的远程跟踪分支的操作​​时,您不会自动拥有它们的本地可编辑副本。

Using Bash,
if you want to checkout all branches:

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

It’s important to note that when you do a fetch that brings down new remote-tracking branches, you don’t automatically have local, editable copies of them.

纵情客 2024-07-17 18:10:14

使用:

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 行:'gitbranch -r'(后跟'gitremoteupdate'以更新远程更改的信息)列出所有远程分支; 'egrep -vw' 用于敲入结果中包含 HEAD 和 master 的条目。

第 3 行:在本地检出时跟踪指定的远程分支。 使用简单的 AWK 来避免“origin/”成为本地分支的后缀。

Use:

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

Explanation:

Line 1: 'git branch -r' (followed by 'git remote update' to update the info on changes to remote) lists all remote branches; 'egrep -vw' is used to knock entries having HEAD and master in the result.

Line 3: Track the named remote branch while checking it out locally. A simple AWK is used to avoid 'origin/' being the suffix for local branches.

樱娆 2024-07-17 18:10:14

使用:

#!/usr/bin/env bash

# Go from a shallow clone of the main branch
# to a deep clone of all branches

# Excluding mounted worktrees is required to avoid errors like:
#    fatal: refusing to fetch into branch 'refs/heads/master' checked out at '/tmp/repo'

remote=${1:-origin}

git fetch $remote --depth=99999999 $(
  git ls-remote --heads $remote |
  cut -d/ -f3- |
  grep -v -x -E $(
    git worktree list --porcelain |
    grep ^branch | cut -c19- | tr 

这将扩展为类似:

git fetch origin --depth=99999999 \
  branch1:branch1 \
  branch2:branch2 \
  branch2:branch3
\n' '|' ) | sed 's/.*/&:&/' )

这将扩展为类似:

Use:

#!/usr/bin/env bash

# Go from a shallow clone of the main branch
# to a deep clone of all branches

# Excluding mounted worktrees is required to avoid errors like:
#    fatal: refusing to fetch into branch 'refs/heads/master' checked out at '/tmp/repo'

remote=${1:-origin}

git fetch $remote --depth=99999999 $(
  git ls-remote --heads $remote |
  cut -d/ -f3- |
  grep -v -x -E $(
    git worktree list --porcelain |
    grep ^branch | cut -c19- | tr 

This will expand to something like:

git fetch origin --depth=99999999 \
  branch1:branch1 \
  branch2:branch2 \
  branch2:branch3
\n' '|' ) | sed 's/.*/&:&/' )

This will expand to something like:

千纸鹤带着心事 2024-07-17 18:10:14

如果您已经签出一些分支并希望

  • 从远程签出所有剩余分支,
  • 请确保所有本地分支都跟踪远程分支,

您可以使用以下 Bash 和 Z shell 兼容脚本:

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

In case you already have some branches checked out and want to

  • check out all remaining branches from the remote
  • make sure all local branches track the remote branches

you can use the following Bash- and Z shell-compatible script:

git branch -r | while read b; do if git branch | grep -q " ${b##*/}
quot;; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done
好倦 2024-07-17 18:10:13

奥托给出的答案很好,但所有创建的分支都将以“origin/”作为名称的开头。 如果您只想将最后一部分(最后一个 / 之后)作为结果分支名称,请使用此命令:

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

它还有一个好处是不会向您发出任何有关不明确引用的警告。

The answer given by Otto is good, but all the created branches will have "origin/" as the start of the name. If you just want the last part (after the last /) to be your resulting branch names, use this:

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

It also has the benefit of not giving you any warnings about ambiguous refs.

甜心小果奶 2024-07-17 18:10:13

使用 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. (错误)所有创建的分支都用于跟踪 master
  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 似乎更喜欢本地分支。

Using 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

credits: Val Blant, elias, and Hugo

Before Git 1.9.1

Note: the following code if used in later versions of Git (>v1.9.1) causes

  1. (bug) All created branches to track master
  2. (annoyance) All created local branch names to be prefixed with origin/
for remote in `git branch -r `; do git branch --track $remote; done

Update the branches, assuming there are no changes on your local tracking branches:

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

Ignore the ambiguous refname warnings, Git seems to prefer the local branch as it should.

神经大条 2024-07-17 18:10:13

这里的大多数答案都使 gitbranch -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 切换到 < code>gitbranch 你可以确认:

$ 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循环的分解

该循环基本上调用命令gitbranch-r,使用grep过滤掉输出中的任何HEAD或master分支 - vE“HEAD|master”。 为了获取减去 origin/ 子字符串的分支名称,我们使用 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

但我并不特别喜欢这种方法,因为它会在您之间切换执行结帐时的分支。 完成后,您将停留在它创建的最后一个分支上。

参考文献

Most of the answers here are over complicating the parsing of the output of git branch -r. You can use the following for loop to create the tracking branches against all the branches on the remote like so.

Example

Say I have these remote branches.

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

Confirm that we're not tracking anything other than master already, locally:

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

You can use this one liner to create the tracking branches:

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

Now confirm:

$ git branch
  development
  integration
* master
  production
  staging

To delete them:

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

If you use the -vv switch to git branch you can confirm:

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

Breakdown of for loop

The loop basically calls the command git branch -r, filtering out any HEAD or master branches in the output using grep -vE "HEAD|master". To get the names of just the branches minus the origin/ substring we use Bash's string manipulation ${var#stringtoremove}. This will remove the string, "stringtoremove" from the variable $var. In our case we're removing the string origin/ from the variable $i.

NOTE: Alternatively you can use git checkout --track ... to do this as well:

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

But I don't particularly care for this method, since it's switching you among the branches as it performs a checkout. When done it'll leave you on the last branch that it created.

References

幸福还没到 2024-07-17 18:10:13

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

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

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

正如我在另一个旧答案中提到的,使用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) 设置。< /p>

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

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

Update Q1 2020: Mohsen Abasi proposes in the comments, based on the 2014 slm's answer, the simpler alternative:

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

And it uses $() instead of obsolete backticks.

As I mention in another old answer, using git for-each-ref is probably faster.
And I would use the new (Git 2.23+) git switch command, which replaces the confusing 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

That way, no grep needed.


Old (2011) original answer:

Here is my one-liner I use (in a bash shell, tested with msysgit1.7.4):

For copy-paste:

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

For more readability:

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
    

That command will create local branches for all remote upstream branches, and set their remote and merge setting to that remote branch.

请叫√我孤独 2024-07-17 18:10:13

没有任何脚本(在空目录中):

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

之后,所有远程分支将被视为本地分支。


原文(俄语)

Without any scripting (in an empty directory):

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

After that, all remote branches will be seen as local.


Original (in Russian).

请你别敷衍 2024-07-17 18:10:13

您可以很容易地编写脚本,但我不知道它什么时候有价值。 这些分支很快就会落后,你必须一直更新它们。

远程分支会自动保持最新状态,因此最简单的方法是在您实际想要处理的位置创建本地分支。

You could script that easily enough, but I don't know when it'd be valuable. Those branches would pretty quickly fall behind, and you'd have to update them all the time.

The remote branches are automatically going to be kept up to date, so it's easiest just to create the local branch at the point where you actually want to work on it.

猫性小仙女 2024-07-17 18:10:13
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done
埋葬我深情 2024-07-17 18:10:13

如果您想使用 powershell 并且您的遥控器称为 origin。 然后这行得通。

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

If you want to use powershell and your remote is called origin. Then this works.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}
雨后彩虹 2024-07-17 18:10:13
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do  git branch --track ${branch##*/} $branch; done

使用这个,你将不会收到这样的警告: refname 'origin/dev' is ambigacy

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

Use this and you will not have such warning as: refname 'origin/dev' is ambiguous

带上头具痛哭 2024-07-17 18:10:13

要执行与 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

To do the same as tjmcewan's answer but on Windows, call this from a batch file:

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

Or this from the command line:

for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r
输什么也不输骨气 2024-07-17 18:10:13

这是我对 @tjmcewan 引用的 Bash 命令的解决方案:

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

我的目标是解决所有创建的分支都以“origin/”作为名称开头的问题,因为我测试了 $remote 变量仍然包含“起源/”:

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

Here is my solution of a Bash command referred to by @tjmcewan:

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

My goal is to solve the problem that all the created branches will have "origin/" as the start of the name, because I tested that $remote variables are still include "origin/":

for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done
雅心素梦 2024-07-17 18:10:13

从 Git 2.23 开始:

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

git switch-C 标志将创建或重置(如果已存在)。

Git 切换文档

From Git 2.23 onwards:

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

The -C flag for git switch creates or resets if it already exists.

Git switch documentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文