git pull是否更新所有跟踪的分支? [英] Does a git pull update all tracked branches?
问题描述
假设我在本地跟踪3个远程分支,即 master
, branch1
, branch2
.
如果我当前在 master
分支上,则 git pull
fetch
和 merge
会发生变化每个分支?
我想我也可以建立一个实验...
简短的答案是否",或者,如果一个人只读了您的问题的标题,甚至可能是否,是",但这有点误导人.
pull命令允许使用选项,其中许多选项具有有趣(且令人困惑,甚至可能非常微妙)的效果.
侧边栏:请确保您正确理解 git fetch 更新远程跟踪分支的 any ,但是从1.8.4开始,显式获取了分支
br
还会更新您的origin/ br
(假设有问题的遥控器名为origin
)./p>如果不传递额外的参数,则
git fetch
将 fetch 远程的默认refspec集,通常为 2 所有分支".这意味着git fetch
(假设origin
)或git fetch origin
都会为origin 更新所有远程跟踪分支.code>,前提是您运行的是相当现代的(1.8.4或更高版本)Git.(在足够老的Git版本中,我认为
pull
命令在获取步骤中变得更加严格.)但是,潜在地获取并更新了所有
origin/*
远程跟踪分支之后,pull
代码就移至了git merge
步.对于这一部分,Git非常在乎您现在在哪个分支上,以及它与哪个远程分支" 3 合并.如您的示例所示,如果您当前位于master
上,并且与origin
的master
合并,则Git将运行git merge
步骤使用origin/master
(请在此处注意斜杠)下引入的所有新内容.技术细节:"refspec"
我使用了"refspec"一词,多次,但从未对其进行定义.
"refspec"倒数第二个,只是一对分支名称,例如
master:master
,develop:develop
等.该对通常(但不总是)在冒号的两侧都具有相同的两个分支名称:
:
.其中之一是您的名称(您的存储库中的分支),另一个是其名称,即名称 they 用于他们的存储库中的他们的分支.通常,您在推送时会看到以下两种形式:例如
git push origin master:master
.这意味着收拾我的主人的东西,通过互联网电话呼叫名为origin
的遥控器,将包裹发送给他,并询问他是否将其作为他的master
分支."您还可以在左侧使用提交ID或单词HEAD
:git push origin HEAD:master
的意思是接受我现在正在进行的任何提交,并且要求远程origin
作为他的master
".进行
git fetch
时,两面会颠倒,通常您还需要在要添加的名称前添加origin/
(或遥控器的名称)你这边也就是说,您得到了 hismaster
,但是在您的存储库中将其称为origin/master
.因此,您git获取原始master:origin/master
,依此类推. 4 如果您执行git获取原始master:master
,您(可能))清除您在自己的主机上所做的工作. 5
fetch
和pull
还有另外一件奇怪的事情.我说这是第二最简单的"方法.refspec的形式.最简单的只是一个简单的名称,例如master
.其含义取决于您正在执行的操作:对于fetch
,它的意思是带来他的master
,但不一定"在我的本地存储库中给它 any 名称,只需保存哈希ID.对于push
,它的意思是给他我的master
,并要求他将其称为master
".同样,在旧版本的git中,如果您要求
git fetch
带来他们的母版(可能还有其他),而不给fetch
一个本地名称以供使用它,它只会 将ID(及其分支的名称)保存在Git的FETCH_HEAD
文件中.在较新的Git(1.8.4及更高版本)中,git使用fetch =
配置条目来确定要更新的远程跟踪分支.丑陋的
git pull origin master分支
(不要这样做)如果您告诉
git fetch
带来几个分支,则可以正常工作(无论如何,对于Git 1.8.4或更高版本).但是,如果您告诉git pull
进行多个分支,则它的行为会很差.
fetch
步骤工作正常.在merge
步骤出现问题.
pull
代码要求git merge
将多个分支合并到您的当前分支中.Git将此称为章鱼合并".除非您要进行高级分支,否则几乎可以肯定不希望这样做.所以不要这样做.底线
我建议您执行一次
git fetch
,默认情况下会进行全部操作,然后再进行单独的git merge
或git rebase
操作.您将能够看到自己在做什么.1 或
git rebase
(如果已配置或定向).变基比合并通常要好,尽管它总是取决于细节.我的建议是先使用git fetch
,然后至少在您使用自己的git rebase
或git merge
作为单独的步骤时,重新接触Git.我认为这种方法实际上 less 令人困惑,尽管您必须输入两个命令而不是一个.2 从技术上讲,这就是该遥控器的配置中
fetch =
行中的内容.远程origin
的常规行读取fetch = + refs/heads/*:refs/remotes/origin/*
,这是git知道如何将起源的分支重命名为起源/任何
分支.3 从技术上讲,Git仅使用原始哈希ID,保存在名为
FETCH_HEAD
的文件中.引号中的术语远程分支是标准的Git术语:正在馈送的存储库中看到的分支名称通过git fetch
命令提交到您的Git.>4 我要再说一件事,这是领先的
+
标志:在获取其主人"时,您通常会忘记以前的任何想法您对他们的主人"有所了解,因此fetch =
行具有前导加号.这开启了力"作用.标志,即即使不是快进操作也要进行更新.fetch =
行还可以将所有内容完全拼写,以免在您意外命名本地分支origin/something
并使用*
字符时避免出现问题匹配多个分支名称.5 如果您做破坏自己的工作,几乎可以随时取回它.Git确实尝试至少坚持30天.我们将保留如何取回"的信息.到其他SO条目.
Say I'm locally tracking 3 remote branches,
master
,branch1
,branch2
.If I'm currently on the
master
branch, will agit pull
fetch
andmerge
changes on each of the branches?I guess I could build out an experiment, too...
解决方案The short answer is "no"—or maybe even "no and yes", if one reads only the title of your question—but this is somewhat misleading.
The pull command allows options, and many of these have interesting (and confusing and potentially very un-nice) effects.
Sidebar: Make sure you correctly understand the differences between what the Git documentation calls remote branches, remote-tracking branches and tracking branches to take full advantage of the following explanations. Note that these are terms that Git (and git-scm.com) use. Long after I wrote this answer originally, I find these terms just confuse people—including me!—and these days, I prefer my own terminology. Instead of remote branch, I like to say branch name as seen on the other (remote) Git repository; instead of remote-tracking branch name (e.g.,
origin/master
), I call this a remote-tracking name; and instead of tracking branch, I use the phrase branch name with an upstream set. But be prepared for Git documentation to use their terminology.Remember,
git pull
is basically shorthand forgit fetch
followed bygit merge
.1 Thepull
command passes most of its arguments right through to thefetch
step. For instance, if yougit fetch origin br
, thefetch
step gets the name of the remote (origin
) andbr
as a "refspec". In versions of Git predating 1.8.4, this preventedgit fetch
from updating any of your remote-tracking branches, but since 1.8.4, explicitly fetching branchbr
also updates yourorigin/br
(assuming the remote in question is namedorigin
).If you don't pass extra arguments,
git fetch
will fetch the default set of refspecs for the remote, which is normally2 "all branches". This means that eithergit fetch
(assumingorigin
) orgit fetch origin
will update all your remote-tracking branches fororigin
, provided you are running a reasonably modern (1.8.4 or later) Git. (In sufficiently old versions of Git I think thepull
command gets more restrictive during the fetch step.)But, having potentially fetched and updated all the
origin/*
remote-tracking branches, thepull
code moves on to thegit merge
step. For this part, Git cares mightily about which branch you're on now, and which "remote branch"3 it merges with. If, as in your example, you're currently onmaster
and it merges withorigin
'smaster
, Git will run thegit merge
step using whatever new stuff it brought in that went underorigin/master
(note the slash here).Technical nitty details: the "refspec"
I used the word "refspec" above several times, without ever defining it.
The "refspec" is, at its second-simplest, just a pair of branch names, like
master:master
,develop:develop
, and the like.The pair usually, but not always, has the same two branch names on both sides of the colon
:
between them. One of these is your name—your branch, in your repository—and the other is their name, that is, the name they use for their branch in their repository.Usually you see this two-names form when pushing:
git push origin master:master
for instance. This means "pack up what I have in my master, call up the remote namedorigin
over the Internet-phone, send him the package, and ask him if he'll make this hismaster
branch." You can also use, on the left, a commit ID or the wordHEAD
:git push origin HEAD:master
means "take whatever commit I'm on now, and ask the remoteorigin
to make that hismaster
".When doing a
git fetch
the sides get reversed, and normally you also addorigin/
(or the name of your remote) in front of the name you want on your side. That is, you get hismaster
, but call itorigin/master
in your repository. So yougit fetch origin master:origin/master
, and so on.4 If you didgit fetch origin master:master
you would (potentially) wipe out work you did on your own master.5There's one other odd thing with
fetch
vspull
. I said this is the "second simplest" form of a refspec. The simplest is just an unadorned name likemaster
. The meaning of this depends on which you're doing: forfetch
, it means "bring over hismaster
, but don't necessarily give it any name in my local repository, just save the hash ID." Forpush
, it means "give him mymaster
and ask him to call itmaster
".Again, in old versions of git, if you asked
git fetch
to bring over their master (and maybe others), without givingfetch
a local name to use for it, it would only save the ID (and their name for the branch) in Git'sFETCH_HEAD
file. In newer (1.8.4 and later) versions of Git, git uses thefetch =
configuration entry to figure out what remote-tracking branch(es) to update.The ugly:
git pull origin master branch
(don't do it)If you tell
git fetch
to bring over several branches, that works fine (with Git 1.8.4 or later anyway). But if you tellgit pull
to take several branches, it behaves badly.The
fetch
step works fine. Things go wrong at themerge
step.The
pull
code asksgit merge
to merge multiple branches into your current branch. Git calls this an "octopus merge". Unless you're into advanced branching, you almost certainly don't want that. So don't do it.Bottom line
I advise doing one
git fetch
, which will by default bring over all, then doing individualgit merge
orgit rebase
ops. You'll be able to see what you're doing.
1Or
git rebase
, if so configured or directed. Rebasing is usually better than merging, though it always depends on details. My advice here is to usegit fetch
first, then do your owngit rebase
orgit merge
as a separate step, at least while you're new to Git. I think it's actually less confusing this way, though admittedly you have to type in two commands instead of just one.2Technically, it's whatever is in the
fetch =
lines in the configuration for that remote. The normal line for remoteorigin
readsfetch = +refs/heads/*:refs/remotes/origin/*
, which is how git knows to rename origin's branches to yourorigin/whatever
branches.3Technically, Git just uses a raw hash ID, saved in a file named
FETCH_HEAD
. The term remote branch here in quotes is the standard Git term: the branch name as seen on the repository that is feeding commits to your Git through yourgit fetch
command.4I'm leaving out one more thing, which is the leading
+
sign: when fetching "their master", you usually want to forget any previous idea you had about "their master", so thefetch =
line has that leading plus sign. This turns on the "force" flag, i.e., update even if it's not a fast-forward operation. Thefetch =
line also spells everything out in full to avoid problems if you accidentally name a local branchorigin/something
, and uses the*
character to match multiple branch names.5If you do clobber your own work, you can almost always get it back. Git really tries to hang on to everything for at least 30 days. We'll leave "how to get it back" to other SO entries though.
这篇关于git pull是否更新所有跟踪的分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!