我可以这样说:
git push --all origin
Run Code Online (Sandbox Code Playgroud)
它会将所有分支推向原点.但如果我这样做:
git pull --all origin
Run Code Online (Sandbox Code Playgroud)
然后它不会从原点拉出所有分支,它只返回一个错误:
fatal: fetch --all does not take a repository argument
Run Code Online (Sandbox Code Playgroud)
好的,我这样做:
git pull --all
Run Code Online (Sandbox Code Playgroud)
买还是说:
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.
Run Code Online (Sandbox Code Playgroud)
那么如何从原点拉出所有分支(就像我将所有分支推送到原点git push --all origin)?
VonC的答案包含了使各种设置工作所需的所有项目,但可以使用一些背景解释来解释那些对git来说有点新的东西.
在我认为是命名的一个非常不幸的有点,git的有fetch,push和pull.这听起来像是 pull相反的方向push,但事实并非如此!push实际上最接近的是相反的fetch(即使那时它们也不是完全对称的).
要正确理解这一切,您需要知道在git中,分支名称只是特定提交的标签,具有一个非常特殊的属性."常规"或"本地"分支名称(通常称为"分支")master具有特殊属性,当您通过分支名称检出并在存储库中进行新提交时,该分支名称会自动向前移动到包括你的新提交.(并且每个新提交都指向其"父"旧提交 - 或者,对于合并,返回其所有父级.)
Git还提供了"远程分支",它(在git传统中)有一个误导性的名称,因为它们也存在于您的存储库中,而不是存在于其他"远程"存储库中.它们以遥控器的名称作为前缀,例如origin,因此您具有origin/master"远程分支".同样,这些只是提交的标签.Unlilke你当地的分支机构,他们在你提交时不会移动 - 但他们确实会移动.他们使用时移动git fetch.
当你运行时git fetch,你的git会联系一些remote(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
Run Code Online (Sandbox Code Playgroud)
普通fetch会带来所有分支,以不同的名称将它们写入您的存储库. 在这种情况下,master变得origin/master和branch变origin/branch.2
为了引入分支标签,它还会带来提交本身(例如222c4dd...上面的内容),以及完成提交所需的任何其他底层对象.(这包括他们拥有的任何开发历史记录,您还没有.)然后,新的远程调整分支名称(origin/branch)被设置为直接指向该commit(222c4dd...).
因此,正如已经指出的那样,git fetch带动所有分支,就像git push --all推动所有分支一样.什么fetch也不会做的是合并所有这些更新到自己的地方分支机构.这也是彼此镜像的地方fetch和push停止:当你push分支到遥控器时,没有自动重命名.3
再一次,当我们带来他们的时候master,它就变成了origin/master.我们的所有分支都没有被命名origin/whatever,所以这不可能破坏我们的分支.但是当我们把master它们推向它们时,我们只是告诉它们将它们设置为它们 master.我们不说:"把我们master推向你的alexander/master".4 这就是为什么,在我们推动之前,我们通常必须合并或重新组合我们master的,所以当我们告诉他们"嘿,设置你master的提交af7c315"时,我们确保这个新的commit-ID包含他们的所有历史记录有,所以他们不会失去任何.
这就是git pull进来.更新自己master,我们需要先带过来的master,有git fetch,将其重命名origin/master我们的本地副本.然后,一旦我们与他们同步,我们合并或重组我们master和我们origin/master(现在与他们同步master).最后,当它完成并且很好的时候,我们可以推动我们的新的master-it's现在基于/合并我们的origin/master匹配master- 他们的master.只要这一切发生得足够快,这一切都有效.(如果它不够快 - 如果其他人击败我们push- 然后我们必须再次获取,再次合并或重组,并push再次尝试,重复直到我们赢得与其他所有人竞争的比赛push.)
该git pull脚本只是自动化fetch-and-merge/rebase部分.但它只用一个分支来做到这一点:我们现在检查的任何分支.这是因为,在git中,merge和rebase命令只更改一个分支:merge合并到当前分支,并rebase通常重新定义当前分支.(如果你告诉git rebase他们改变一些其他的分支,它首先检查它.)
如果要合并或重新绑定多个分支,则必须逐个检查每个分支.(rebase从git rebase origin/master master开始做git checkout master起来稍微容易一点 - 所以它内置于命令中 - 但你仍然在做git checkout.)幸运的是,它git fetch origin会立即更新所有的远程分支,所以你只需要一个git fetch.
Git通常假设除非您计划在分支中更改某些内容,或者在特定提交时冻结它,否则您不会检查自己的版本.也就是说,你不这样做:
$ git checkout --track feature origin/feature
Run Code Online (Sandbox Code Playgroud)
除非你打算用它做点什么.因此,除非你已经在分支机构feature,否则没有调用rebase或merge它.
因为git clone通常是初始结账,master而人们经常在功能分支上工作,所以最常见的是结束你将要工作的一个分支(feature)和一个你不需要的本地分支(master).但是,离开那个分支进一步落后origin/master直到你确实需要它是没有错的; 或者你甚至可以删除它,一旦你做了git checkout一些其他分支:
$ 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).
$
Run Code Online (Sandbox Code Playgroud)
(警告很烦人但无害).
1该fetch还可以看到标记和其他裁判,并且可以指示它带来更多的东西了.上面的例子显示了一个标签HEAD.添加--tags或更改fetch =行允许您将标记结束.该HEAD基准是格外特别,并且有一个在git的方式对待一个长期存在的细微错误HEAD的克隆操作,这通常不是重要的,需要在协议的改变来解决,所以没有人固定它.
2更准确地说,refs/heads/*映射到正在复制refs/remotes/origin/*的*部分.所以,如果遥控器有一个refs/heads/this/that,你得到refs/remotes/origin/this/that.这就是文件中定义fetch =下的行:它告诉我们如何重新映射远程引用.这也是我说"正常"获取的原因:您可以配置它,或者使用选项运行它,以使其行为不同.remote.git/configfetch
git的新手可能会想知道为什么要重命名.好吧,假设你从抓住他们master并建立一个新的本地master分支开始,这样你就可以改变一切.然后你改变一些东西,并使用git add和git commit创建至少一个新的提交.与此同时,他们(无论他们是谁)也改变了事情并做出了新的承诺.你想看看他们做了什么,所以你要git fetch他们的新东西.如果那覆盖了你master,你的工作会怎样?幸运的是,git以不同的名字带来了他们的新东西:origin/master.您的master保持不变,跟踪您的新提交.
3至少,不是默认情况下.与大多数git一样,您可以使用命令行标志和配置条目更改此行为.
4实际上,正如脚注3中已经提到的那样,我们可以做到这一点,在某些设置中,您甚至可能想要这样做.但是,人们通常不会将git用于共享存储库.
git pull与第一git fetch的一切,这意味着origin命名空间将包括所有(远程跟踪)分支从origin(见取所有分支)。
但它只会合并origin/currentBranch到currentBranch.
它不会创建其他分支。
如果要从 中创建所有分支origin,则您的 git 分支将被上游存储库的潜在许多分支“污染”。
通常,您只希望将要处理的分支作为本地分支。
如果要从远程跟踪所有分支,可以参考问题“将所有远程 git 分支跟踪为本地分支”中的这一单行。