繁体   English   中英

如何获取所有 Git 分支?

[英]How do I fetch all Git branches?

我克隆了一个包含许多分支的 Git 存储库。 但是, git branch只显示一个:

$ git branch
* master

我将如何在本地拉所有分支,所以当我执行git branch时,它显示以下内容?

$ git branch
* master
* staging
* etc...

TL;DR 答案

git branch -r | grep -v '\->' | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all

(似乎 pull 会从所有遥控器中获取所有分支,但我总是先获取以确保。)

仅当服务器上存在本地分支未跟踪的远程分支时才运行第一个命令。

完整答案

您可以像这样从所有遥控器获取所有分支:

git fetch --all

这基本上是一个权力的举动

fetch更新远程分支的本地副本,因此这对您的本地分支始终是安全的,但是

  1. fetch不会更新本地分支(跟踪远程分支); 如果你想更新你的本地分支,你仍然需要拉每个分支。

  2. fetch不会创建本地分支(跟踪远程分支),您必须手动执行此操作。 如果要列出所有远程分支: git branch -a

更新跟踪远程分支的本地分支:

git pull --all

然而,这仍然是不够的。 它仅适用于跟踪远程分支的本地分支。 要跟踪所有远程分支,请在git pull --all之前执行此 oneliner:

git branch -r | grep -v '\->' | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" | while read remote; do git branch --track "${remote#origin/}" "$remote"; done

PS AFAIK git fetch --allgit remote update是等价的。



Kamil Szot 的评论,人们发现这很有用。

我不得不使用:

 for remote in `git branch -r`; do git branch --track ${remote#origin/} $remote; done

因为您的代码创建了名为origin/branchname的本地分支,并且每当我提到它时,我都会得到“refname 'origin/branchname' 是模棱两可的。

列出远程分支:

git branch -r

要将远程分支检出为本地分支:

git checkout -b local_branch_name origin/remote_branch_name

您将需要创建本地分支来跟踪远程分支。

假设您只有一个名为origin的远程,此代码段将为所有远程跟踪创建本地分支:

for b in `git branch -r | grep -v -- '->'`; do git branch --track ${b##origin/} $b; done

之后, git fetch --all将更新远程分支的所有本地副本。

此外, git pull --all将更新您的本地跟踪分支,但取决于您的本地提交以及“合并”配置选项的设置方式,它可能会创建合并提交、快进或失败。

如果你这样做:

git fetch origin

然后他们将都在当地。 如果您随后执行:

git branch -a

你会看到它们被列为远程/来源/分支名称。 由于他们在当地,您可以随心所欲地对待他们。 例如:

git diff origin/branch-name 

或者

git merge origin/branch-name

或者

git checkout -b some-branch origin/branch-name
$ git remote update
$ git pull --all

这假设所有分支都被跟踪。

如果不是,您可以在 Bash 中触发:

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

然后运行命令。

Bash for循环对我不起作用,但这正是我想要的。 我的所有分支都在本地镜像为同名。

git checkout --detach
git fetch origin '+refs/heads/*:refs/heads/*'

请参阅下面的Mike DuPont的评论。 我想我试图在 Jenkins 服务器上执行此操作,使其处于分离头模式。

使用git fetch && git checkout RemoteBranchName

它对我来说效果很好......

当您克隆存储库时,实际上会下载分支的所有信息,但分支是隐藏的。 用命令

$ git branch -a

您可以显示存储库的所有分支,并使用命令

$ git checkout -b branchname origin/branchname

然后,您可以一次手动“下载”它们。


但是,有一种更清洁、更快捷的方法,尽管它有点复杂。 您需要三个步骤来完成此操作:

  1. 第一步

    在您的机器上创建一个新的空文件夹并从存储库中克隆 .git 文件夹的镜像副本:

     $ cd ~/Desktop && mkdir my_repo_folder && cd my_repo_folder $ git clone --mirror https://github.com/planetoftheweb/responsivebootstrap.git .git

    文件夹 my_repo_folder 中的本地存储库仍然是空的,现在只有一个隐藏的 .git 文件夹,您可以从终端使用“ls -alt”命令查看。

  2. 第二步

    通过将 git 配置的布尔值“bare”切换为 false,将此存储库从空(裸)存储库切换到常规存储库:

     $ git config --bool core.bare false
  3. 第三步

    获取当前文件夹中的所有内容并在本地计算机上创建所有分支,因此使其成为正常的存储库。

     $ git reset --hard

所以现在你可以输入命令git branch并且你可以看到所有的分支都被下载了。

这是您可以一次克隆包含所有分支的 git 存储库的快速方法,但您不想以这种方式为每个项目执行此操作。

您可以通过以下方式获取所有分支:

git fetch --all

或者:

git fetch origin --depth=10000 $(git ls-remote -h -t origin)

如果您已经浅化了存储库, --depth=10000参数可能会有所帮助。


要拉出所有分支,请使用:

git pull --all

如果上面不起作用,那么在上面的命令之前加上:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

因为remote.origin.fetch在获取时只能支持特定的分支,尤其是当您使用--single-branch克隆存储库时。 通过以下方式检查: git config remote.origin.fetch

之后,您应该能够签出任何分支。

也可以看看:


要将所有分支推送到远程,请使用:

git push --all

最终--mirror镜像所有参考。


如果您的目标是复制存储库,请参阅:在 GitHub 上复制存储库文章。

我通常只使用这样的命令:

git fetch origin
git checkout --track origin/remote-branch

稍微短一点的版本:

git fetch origin
git checkout -t origin/remote-branch

您看不到远程分支,因为您没有跟踪它们。

  1. 确保您正在跟踪所有远程分支(或任何您想要跟踪的分支)
  2. 更新您的本地分支以反映远程分支。

跟踪所有远程分支:

跟踪远程仓库中存在的所有分支。

手动执行:

您可以将<branch>替换为从git branch -r的输出中显示的分支。

git branch -r
git branch --track <branch>

使用 bash 脚本执行此操作:

for i in $(git branch -r | grep -vE "HEAD|master"); do git branch --track ${i#*/} $i; done

懒惰的方式(由于合并冲突,这可能会造成混乱,请小心):

git checkout master
git pull

更新有关本地计算机上远程分支的信息:

这会从您在本地存储库中跟踪的远程存储库中获取分支上的更新。 这不会改变您当地的分支机构。 您的本地 git repo 现在知道远程 repo 分支上发生的事情。 一个例子是,一个新的提交已经被推送到远程主控,现在做一个提取会提醒你你的本地主控落后了 1 个提交。

git fetch --all

在本地计算机上更新有关远程分支的信息并更新本地分支:

对从远程分支到本地分支的所有分支进行提取,然后合并。 一个例子是一个新的提交已经被推送到远程主控,执行拉取将更新你的本地仓库关于远程分支中的更改,然后它将这些更改合并到你的本地分支中。 由于合并冲突,这可能会造成相当混乱。

git pull --all

如果您在这里寻求解决方案来获取所有分支,然后将所有内容迁移到另一个 Git 服务器,我将以下过程放在一起。 如果您只想在本地更新所有分支,请在第一个空行处停止。

git clone <ORIGINAL_ORIGIN>
git branch -r | awk -F'origin/' '!/HEAD|master|main/{print $2 " " $1"origin/"$2}' | xargs -L 1 git branch -f --track 
git fetch --all --prune --tags
git pull --all

git remote set-url origin <NEW_ORIGIN>
git pull
<resolve_any_merge_conflicts>
git push --all
git push --tags
<check_NEW_ORIGIN_to_ensure_it_matches_ORIGINAL_ORIGIN>

我相信您已经通过以下方式克隆了存储库:

git clone https://github.com/pathOfrepository

现在使用 cd 转到该文件夹​​:

cd pathOfrepository

如果你输入git status你可以看到所有:

   On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

查看所有隐藏的分支类型:

 git branch -a

它将列出所有远程分支。

现在,如果您想在任何特定分支上结帐,只需键入:

git checkout -b localBranchName origin/RemteBranchName

确保所有远程分支都可以在.git/config文件中获取。

在这个例子中,只有origin/production分支是可获取的,即使你尝试执行git fetch --all ——除了获取production分支之外什么都不会发生:

[origin]
fetch = +refs/heads/production:refs/remotes/origin/production

此行应替换为:

[origin]
fetch = +refs/heads/*:refs/remotes/origin/*

然后运行git fetch等...

克隆主存储库后,您只需执行

git fetch && git checkout <branchname>

如何获取跟踪单个远程的所有 Git 分支。

这已经在 Windows 10 上的 Red Hat 和 Git Bash 上进行了测试和功能。


TLDR:

for branch in `git branch -r|grep -v ' -> '|cut -d"/" -f2`; do git checkout $branch; git fetch; done;

解释:

一个班轮签出,然后获取除 HEAD 之外的所有分支。

列出远程跟踪分支。

git branch -r

忽略头。

grep -v ' -> '

从遥控器中取出分支名称。

cut -d"/" -f2

结帐跟踪单个遥控器的所有分支机构。

git checkout $branch

获取已签出的分支。

git fetch

从技术上讲,新的本地分支不需要获取。

这可用于fetchpull取新分支并且在远程中具有更改。

只需确保仅在准备合并时才拉动。


测试设置

使用 SSH URL 查看存储库。

git clone git@repository.git

检查当地的分支机构。

$ git branch
* master

执行命令

执行一个班轮。

for branch in `git branch -r|grep -v ' -> '|cut -d"/" -f2`; do git checkout $branch; git fetch; done;

检查本地分支是否包括远程分支。

$ git branch
  cicd
  master
* preprod

循环似乎对我不起作用,我想忽略起源/主人。 这对我有用。

git branch -r | grep -v HEAD | awk -F'/' '{print $2 " " $1"/"$2}' | xargs -L 1 git branch -f --track

在那之后:

git fetch --all
git pull --all

只需这三个命令即可获取所有分支:

git clone --mirror repo.git  .git     (gets just .git  - bare repository)

git config --bool core.bare false

git reset --hard

对于使用 PowerShell 的 Windows 用户:

git branch -r | ForEach-Object {
    # Skip default branch, this script assumes
    # you already checked-out that branch when cloned the repo
    if (-not ($_ -match " -> ")) {
        $localBranch = ($_ -replace "^.*?/", "")
        $remoteBranch = $_.Trim()
        git branch --track "$localBranch" "$remoteBranch"
    }
}; git fetch --all; git pull --all

设置别名:(根据置顶答案)

git config --global alias.track-all-branches '!git fetch --all && for remote in `git branch -r`; do git branch --track ${remote#origin/} $remote; done && git fetch --all'

现在跟踪所有分支:

git track-all-branches

我写了一个小脚本来管理克隆一个新的 repo 并为所有远程分支创建本地分支。

您可以在这里找到最新版本:

#!/bin/bash

# Clones as usual but creates local tracking branches for all remote branches.
# To use, copy this file into the same directory your git binaries are (git, git-flow, git-subtree, etc)

clone_output=$((git clone "$@" ) 2>&1)
retval=$?
echo $clone_output
if [[ $retval != 0 ]] ; then
    exit 1
fi
pushd $(echo $clone_output | head -1 | sed 's/Cloning into .\(.*\).\.\.\./\1/') > /dev/null 2>&1
this_branch=$(git branch | sed 's/^..//')
for i in $(git branch -r | grep -v HEAD); do
  branch=$(echo $i | perl -pe 's/^.*?\///')
  # this doesn't have to be done for each branch, but that's how I did it.
  remote=$(echo $i | sed 's/\/.*//')
  if [[ "$this_branch" != "$branch" ]]; then
      git branch -t $branch $remote/$branch
  fi
done
popd > /dev/null 2>&1

要使用它,只需将它复制到您的 git bin 目录(对我来说,就是C:\Program Files (x86)\Git\bin\git-cloneall ),然后在命令行上:

git cloneall [standard-clone-options] <url>

它像往常一样克隆,但为所有远程分支创建本地跟踪分支。

这是我认为可靠的东西:

  • 不更新现有分支机构的远程跟踪
  • 不尝试更新HEAD以跟踪origin/HEAD
  • 允许命名为origin以外的遥控器
  • 正确引用外壳
for b in $(git branch -r --format='%(refname:short)'); do
  [[ "${b#*/}" = HEAD ]] && continue
  git show-ref -q --heads "${b#*/}" || git branch --track "${b#*/}" "$b";
done
git pull --all

不需要git fetch --all ,因为将-all传递给git pull会将此选项传递给内部fetch

归功于这个答案

|‾‾‾‾‾‾‾‾‾‾‾‾‾fetch/clone‾‾‾‾‾‾‾‾‾‾‾‾↓   |‾‾‾‾‾‾‾‾‾‾‾‾checkout‾‾‾‾‾‾‾‾‾‾↓   
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾pull‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾↓
Remote repository (`origin`) <=> Local repository <=> Index <=> Workspace
↑_________________push_______________|   ↑____commit____|  ↑____add_____| 

# 拉取远程仓库所有分支信息 → 本地仓库
# fetch all remote repository branch meta → local repository
git remote set-branches origin '*'
git fetch -v

# 把所有远程分支数据搞到本地
# fetch all remote repository branch data → local repository
git branch -r | grep -v '\->' | while read remote; do git branch "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all

您可以通过这一行命令获取所有分支,如下所示:

git fetch --all && git pull --all && git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done

如果您在使用fetch --all时遇到问题,请跟踪您的远程分支:

git checkout --track origin/%branchname%

我们可以将所有分支或标签名称放在一个临时文件中,然后为每个名称/标签执行 git pull:

git branch -r | grep origin | grep -v HEAD| awk -F/ '{print $NF}' > /tmp/all.txt
git tag -l >> /tmp/all.txt
for tag_or_branch in `cat /tmp/all.txt`; do git checkout $tag_or_branch; git pull origin $tag_or_branch; done

这是接受的答案中提供的单行代码的 Perl 版本:

git branch -r | perl -e 'while(<>) {chop; my $remote = $_; my ($local) = ($remote =~ /origin\/(.*)/); print "git branch --track $local $remote\n";}' > some-output-file

如果您愿意,可以将输出文件作为 Shell 脚本运行。

我们无意中删除了我们的 Stash 项目存储库。 幸运的是,有人在意外丢失之前创建了一个分叉。 我将叉子克隆到我的本地(将省略我如何做到这一点的细节)。 一旦我将叉子完全放在本地,我就跑了一个单线。 我修改了远程的 URL(在我的例子中是源)指向我们正在恢复的目标存储库:

git remote set-url origin <remote-url>

最后将所有分支推到原点,如下所示:

git push --all origin

我们又开始营业了。

为避免错误消息“致命:名为 'origin/master' 的分支已存在。” ,你可以试试我的解决方案:

git branch -r | grep -v '\->'  | grep -v `git branch | awk '/\*/ { print $2; }'`| while read remote; do git branch --track "${remote#origin/}" "$remote"; done

尝试了很多方法,只有这个简单并且对我有用。

for branch in $(git ls-remote -h git@<your_repository>.git | awk '{print $2}' | sed 's:refs/heads/::')
do
  git checkout "$branch"
  git pull
done

根据 Learath2 的回答,这是我在执行git clone [...]cd -ing 进入创建的目录后所做的:

git branch -r | grep -v master | awk {print\$1} | sed 's/^origin\/\(.*\)$/\1 &/' | xargs -n2 git checkout -b

为我工作,但我不知道它会为你工作。 当心。

git remote add origin https://yourBitbucketLink

git fetch origin

git checkout -b yourNewLocalBranchName origin/requiredRemoteBranch (use tab :D)

现在,您的本地yourNewLocalBranchName是您的requiredRemoteBranch

对于 Visual Studio 用户,在包管理器控制台上:

git branch | %{ git fetch upstream; git merge upstream/master}

TLDR为每个远程跟踪分支创建一个本地分支可能是个坏主意。 这些不同类型的分支机构服务于不同的目的,本地分支机构通常是根据他们的需要创建的。 git branch显示本地分支git branch -r显示远程跟踪分支。 git branch -a两者都显示。 您可以使用适当的 fetch 命令更新所有远程跟踪分支。 这通常应该是你所需要的。


滚动浏览现有答案后,我看到了两种类型:那些只是简单地回答所提出的问题,而不是提出不同的方法。 那些提出不同方法但没有解释原因的人。 这是我试图解释更多一点的尝试。

通常的 git 存储库实际上需要处理三种分支。 这三种分支服务于不同的目的。 简而言之:

  • 远程分支:这些是存在于远程存储库中的分支。 您永远不会直接从远程分支读取。 远程分支的所有读取都通过 gits 进行,即所谓的“远程跟踪分支”

  • 远程跟踪分支:git 保留远程分支的本地快照,最准确地称为“远程跟踪分支”。 当您调用git fetchgit pull (它执行提取)时,它们会更新。 您通常可以使用远程跟踪分支而无需创建本地分支。

    例如:

     git merge origin/master

    将远程跟踪分支origin/master合并到当前本地分支中,而不需要您先创建它的本地副本。 这意味着:有一个名为origin/master的远程跟踪分支,它是名为master的分支的快照,因为它存在于名为origin的远程存储库中。 此命令会将其合并到当前签出的本地分支中。 您可能希望在执行此类操作之前进行提取。

  • 本地分支:这些是历史上某些点的手动创建的快照(通常基于远程跟踪分支,至少一开始是这样)。 它们比其他类型更静态,并且只有在您手动更改它们时才会真正改变。 逐个。 如果你想在你的工作树(项目目录)中查看它的内容,或者你想向它添加提交,你可能需要一个本地分支。

完成本地分支(并发布其内容)后,您可以考虑将其删除。 这样您就不需要保持最新状态。 毕竟,fetch 不会更新当前本地分支,而 pull 只会更新当前签出的本地分支。 换句话说:您应该只在需要时创建本地分支,并且在不再需要时应该删除它们。

说“默认情况下隐藏某些分支”可能并不准确。 相反,创建git branch命令是为了向您显示“本地分支”。 您可以使用git branch -r列出远程跟踪分支,使用git branch -a显示本地分支和远程跟踪分支。 这两种不同类型的分支服务于不同的目的,您可能不需要为每个远程跟踪一个本地分支。

另请注意,创建名称以远程名称开头后跟斜杠的本地分支通常是一个坏主意(例如,创建一个名为“origin/master”的本地分支往往是一个坏主意,因为它的名称与远程跟踪分支的名称)。

在更新分支的上下文中,讨论不同风格的 fetch 命令确实有意义:

  • git fetch :仅更新远程与当前签出分支的“上游”中使用的远程匹配的远程跟踪分支。 如果签出的分支没有上游集,则返回到从名为“origin”的远程获取(如果存在)。 这个命令是最简单的,大多数时候就足够了。
  • git fetch --all :更新所有远程跟踪分支,无论它们属于哪个远程快照。

我特别喜欢

git fetch -tf --all

这也将始终更新(并在需要时覆盖)所有标签,包括无法从远程分支访问的标签。

玩git的时候要小心,一步一步来。

$ git remote update  //This will update your local
$ git branch -a      //This will list all the branches(After updating you can now 
see the new branch in the list)
$ git checkout your_branch_name

这个现成的 McAnswer 基于这个(赞成的)答案(转换为处理边缘情况的循环,例如 master、HEAD 和 origin/branch):

$ for REMOTE_BRANCH in `git branch -r | grep -v "HEAD\|master"`; do git checkout -b $REMOTE_BRANCH $REMOTE_BRANCH; done

*请注意,我们还从远程分支名称中删除了/origin以避免重复( /origin/origin/$REMOTE_BRANCH )。

如果您按顺序命名分支以允许循环索引而不是非结构化名称,则可以为自己节省很多问题:

$ for NUM in {1..10}; do git checkout -b app$NUM --track origin/app$NUM; done

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM