git pull是否更新所有跟踪的分支? [英] Does a git pull update all tracked branches?

查看:192
本文介绍了git pull是否更新所有跟踪的分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在本地跟踪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/(或遥控器的名称)你这边也就是说,您得到了 his master ,但是在您的存储库中将其称为 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 a git pull fetch and merge 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 for git fetch followed by git merge.1 The pull command passes most of its arguments right through to the fetch step. For instance, if you git fetch origin br, the fetch step gets the name of the remote (origin) and br as a "refspec". In versions of Git predating 1.8.4, this prevented git fetch from updating any of your remote-tracking branches, but since 1.8.4, explicitly fetching branch br also updates your origin/br (assuming the remote in question is named origin).

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 either git fetch (assuming origin) or git fetch origin will update all your remote-tracking branches for origin, provided you are running a reasonably modern (1.8.4 or later) Git. (In sufficiently old versions of Git I think the pull command gets more restrictive during the fetch step.)

But, having potentially fetched and updated all the origin/* remote-tracking branches, the pull code moves on to the git 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 on master and it merges with origin's master, Git will run the git merge step using whatever new stuff it brought in that went under origin/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 named origin over the Internet-phone, send him the package, and ask him if he'll make this his master branch." You can also use, on the left, a commit ID or the word HEAD: git push origin HEAD:master means "take whatever commit I'm on now, and ask the remote origin to make that his master".

When doing a git fetch the sides get reversed, and normally you also add origin/ (or the name of your remote) in front of the name you want on your side. That is, you get his master, but call it origin/master in your repository. So you git fetch origin master:origin/master, and so on.4 If you did git fetch origin master:master you would (potentially) wipe out work you did on your own master.5

There's one other odd thing with fetch vs pull. I said this is the "second simplest" form of a refspec. The simplest is just an unadorned name like master. The meaning of this depends on which you're doing: for fetch, it means "bring over his master, but don't necessarily give it any name in my local repository, just save the hash ID." For push, it means "give him my master and ask him to call it master".

Again, in old versions of git, if you asked git fetch to bring over their master (and maybe others), without giving fetch a local name to use for it, it would only save the ID (and their name for the branch) in Git's FETCH_HEAD file. In newer (1.8.4 and later) versions of Git, git uses the fetch = 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 tell git pull to take several branches, it behaves badly.

The fetch step works fine. Things go wrong at the merge step.

The pull code asks git 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 individual git merge or git 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 use git fetch first, then do your own git rebase or git 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 remote origin reads fetch = +refs/heads/*:refs/remotes/origin/*, which is how git knows to rename origin's branches to your origin/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 your git 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 the fetch = line has that leading plus sign. This turns on the "force" flag, i.e., update even if it's not a fast-forward operation. The fetch = line also spells everything out in full to avoid problems if you accidentally name a local branch origin/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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆