从原点拉出所有分支

时间:2014-06-10 22:37:53

标签: git

我可以这样说:

git push --all origin

它会将所有分支推送到原点。但如果我这样做:

git pull --all origin

然后它没有所有分支来自来源,它只会返回一个错误:

fatal: fetch --all does not take a repository argument

好的,我这样做:

git pull --all

买它说:

You asked to pull from the remote '--all', but did not specify
a branch. Because this is not the default configured remote
for your current branch, you must specify a branch on the command line.

那么如何从原点拉出所有分支(比如我推送所有分支来源git push --all origin)?

2 个答案:

答案 0 :(得分:7)

VonC's answer包含使各种设置工作所需的所有项目,但可以使用一些背景说明来解释那些对git来说有点新的内容。

我认为这是一个非常不幸的命名,git有fetchpushpull听起来像 pullpush的相反方向,但它不是! push最接近的对象实际上是fetch(即使这样,它们也不是完全对称的)。

要正确理解这一切,您需要知道在git中,分支名称仅仅是用于特定提交的标签,具有一个非常特殊的属性。 A"常规"或者"本地"分支名称 - 通常只是调用"分支"类似master具有特殊属性,当您通过分支名称检出它然后在您的存储库中进行新提交时,该分支名称自动前进以包含您的新提交。 (并且每个新提交都会返回其父级"较旧的提交 - 或者,对于合并,返回其所有父级。)

Git还提供"远程分支",(在git传统中)有一个有点误导性的名称,因为它们也存在于你的存储库中,而不是其他一些"远程"库。它们以远程名称作为前缀,例如origin,因此您将origin/master作为"远程分支"。同样,这些只是提交的标签。 Unlilke你当地的分支机构,他们在你提交时不会移动 - 但他们移动。当您使用git fetch时,它们会移动。

当您运行git fetch时,您的git会联系一些远程(origin)并询问它有哪些分支 1 ,以及这些标签指向的内容。您可以通过运行git ls-remote

来查看此内容
$ git ls-remote
From ssh://[redacted]
d1574b852963482d4b482992ad6343691082412f    HEAD
222c4dd303570d096f0346c3cd1dff6ea2c84f83    refs/heads/branch
d1574b852963482d4b482992ad6343691082412f    refs/heads/master
d41117433d7b4431a188c0eddec878646bf399c3    refs/tags/tag-foo

正常fetch所有分支带入,并以不同的名称将它们写入您的存储库。在这种情况下,master变为{ {1}}和origin/master变为branch 2

为了引入分支标签,它还会带来提交本身(例如上面的origin/branch),以及完成提交所需的任何其他底层对象。 (这包括他们拥有的任何开发历史记录,您还没有。)然后,新的远程调整分支名称(222c4dd...)设置为直接指向该提交({{1} })。

因此,正如已经指出的那样,origin/branch会带来所有分支,就像222c4dd...推送所有分支一样。 {em} 这也是git fetchgit push --all停止彼此镜像的地方:当你fetch分支到远程时,没有自动重命名 3

同样,当我们带领他们的fetch时,它会变成push。我们的所有分支都没有被命名为push,因此这可能会破坏我们的分支。但是,当我们将master推送给他们时,我们只是告诉他们将其设置为他们的 origin/master。我们不会说:"将我们的origin/whatever推送到您的master"。 4 这就是为什么在我们推动之前,我们通常会要么将我们的master与他们合并或改变,那么当我们告诉他们时,请将master设置为alexander/master",我们会确保这一点新的提交ID包含了他们拥有的所有历史记录,因此他们不会丢失任何历史记录。

这是master的用武之地。要更新他们的master,我们需要首先使用af7c315移植git pull,然后重命名master master在我们的本地副本中。然后,一旦我们与他们同步,我们就合并或重新定义我们的git fetch和我们的origin/master(现在与他们的master同步)。最后,当这完成并且很好的时候,我们可以推送新的origin/master - 它现在基于/ master与其master相匹配 - 他们的origin/master。只要这一切发生得足够快,这一切都有效。 (如果它不够快 - 如果有其他人将我们打败到master - 那么我们必须再次获取,合并或重新绑定,然后再次尝试master,重复直到我们赢得了与其他所有人竞争push的比赛。)

push脚本只是自动化fetch-and-merge / rebase部分。但它只使用一个分支:我们现在检查的分支。这是因为,在git中,pushgit pull命令只更改一个分支:merge合并到当前分支,rebase通常会重新绑定当前分支。 (如果你告诉merge重新绑定一些其他分支,它首先检查它。)

如果要合并或重新绑定多个分支,则必须逐个检查每个分支。 (rebase git rebaserebase开始,因为它内置于命令中,所以git rebase origin/master master稍微容易一点 - 但你仍然在做git checkout master。)幸运的是,git checkout会立即更新所有远程分支,因此您只需要一个git fetch origin

Git通常会假设,除非您计划在某个分支中更改某些内容,或者在特定提交时冻结它,否则您不会查看自己的版本。也就是说,你不做:

git fetch

除非你打算用它做点什么。因此,除非您已经在分支机构$ git checkout --track feature origin/feature 上,否则无法调整或合并它。

由于feature执行了初始结帐,通常是git clone,而人们经常在功能分支上工作,所以结束一个分支你很常见on(master)和您不需要的一个本地分支(feature)。但是,只有离开那个分支才能在master之后越来越远,直到你确实需要它为止,这没什么不对。或者你甚至可以删除它,一旦你完成了其他分支的origin/master

git checkout

(警告令人讨厌但无害)。


1 $ git checkout branch # newer gits do --track automatically Branch branch set up to track remote branch branch from origin. Switched to a new branch 'branch' $ git branch -d master warning: deleting branch 'master' that has been merged to 'refs/remotes/origin/master', but not yet merged to HEAD. Deleted branch master (was d1574b8). $ 也可以看到标签和其他参考,你可以指示它带来更多东西。上面的示例显示了一个标记,加上fetch。添加HEAD或更改--tags行可让您将标记结束。 fetch =引用是特殊的,并且git以HEAD的方式处理克隆操作的方式存在长期存在的微妙错误,这通常并不重要,需要将协议更改为修复,所以没有人修复它。

2 更确切地说,HEAD映射到refs/heads/*refs/remotes/origin/*部分被复制。因此,如果遥控器有*,则会获得refs/heads/this/that。这就是refs/remotes/origin/this/that文件中fetch =定义下的remote行的内容:它告诉.git/config如何重新映射远程引用。这也是为什么我说"正常" fetch:您可以对其进行配置,或者使用选项运行它,以使其以不同的方式运行。

git的新手可能会想知道为什么要重命名。好吧,假设您首先抓住他们的fetch并创建一个新的本地master分支,以便您可以更改内容。然后,您更改了一些内容,并使用mastergit add创建至少一个新提交。与此同时,他们(无论他们"他们是谁)改变了事情并做了新的提交。你想看看他们做了什么,所以你git commit他们的新东西。如果这覆盖了您的git fetch,那么您的工作会怎样?幸运的是,git以不同的名称带来了他们的新东西:master。您的origin/master保持不变,跟踪您的新提交。

3 至少,不是默认情况下。与大多数git一样,您可以使用命令行标志和配置条目来更改此行为。

4 实际上,正如脚注3中已经提到的那样,我们可以完全这样做,在某些设置中,您甚至可能想要 。但是,人们通常不会将git用于共享存储库。

答案 1 :(得分:4)

git pull第一个git fetch,意味着origin命名空间将包含来自origin的所有(remote tracking) branches(请参阅fetch all branches)。

但它只会origin/currentBranch合并到currentBranch

它不会创建其他分支。

如果要从origin创建 all 分支,您的git分支将被上游回购的潜在多个分支“污染”。
通常,您只需要将您正在处理的分支作为本地分支。

如果您想跟踪远程的所有分支,可以参考问题“this one-liner”中的Track all remote git branches as local branches