git pull会更新所有被跟踪的分支吗?

bnlyeluc  于 2022-12-25  发布在  Git
关注(0)|答案(4)|浏览(287)

假设我正在本地跟踪3个远程分支机构masterbranch1branch2
如果我当前在master分支上,git pullfetchmerge是否会在每个分支上发生变化?
我想我也可以做个实验...

wixjitnu

wixjitnu1#

简短的回答是“不”--或者,如果只看问题的标题,甚至可能是“不和是”--但这多少有些误导。
pull命令允许选项,其中许多选项都有有趣的(令人困惑的,可能非常不好的)效果。

**边栏:**确保你正确理解了differences between what the Git documentation calls remote branches, remote-tracking branches and tracking branches,以充分利用下面的解释。注意,这些是Git(和git-scm.com)使用的术语。在我最初写下这个答案很久之后,我发现这些术语只会让人困惑--包括我!--最近,我更喜欢我自己的术语。我喜欢说 * 在另一个(远程)Git仓库中看到的分支名称,而不是 * 远程分支 ; 代替 * 远程跟踪分支名称 (例如,origin/master),我将其称为 * 远程跟踪名称; 我使用短语 branch name with a upstream set 代替了 *tracking分支 *,但是要为Git文档使用他们的术语做好准备。

请记住,git pull基本上是git fetch后跟git merge的简写。1 pull命令将其大部分参数直接传递到fetch步骤。fetch步骤获取远程数据库的名称(origin)和br作为“refspec”。在1.8.4之前的Git版本中,这会阻止git fetch更新 * 任何 * 远程跟踪分支,但是从1.8.4开始,显式获取分支 * br * 也会更新您的origin/*br*(假设所讨论的远程名为origin)。
如果不传递额外的参数,git fetch将为远程节点 * 获取 * 默认的refspecs集,通常为2“所有分支”。(假设origin)或git fetch origin将更新origin的所有远程跟踪分支,前提是你运行的是相当现代的Git(1.8.4或更高版本)(在相当老的Git版本中,我认为pull命令在fetch步骤中会受到更多限制)。
但是,在获取并更新了所有origin/*远程跟踪分支之后,pull代码将继续执行git merge步骤。对于这一步,Git非常关心你现在所在的分支,以及它与哪个“远程分支“3合并。如果你当前在master上,并且它与originmaster合并,Git将使用它在origin/master下引入的任何新内容来运行git merge步骤(注意这里的斜线)。

技术细节:“参考规范”

我在上面多次使用“refspec”这个词,但从未定义过它。
“refspec”是一对分支名称,如master:masterdevelop:develop等。
这对分支通常(但并不总是)在冒号:的两边有两个相同的分支名称,其中一个是 your name--你的分支,在你的仓库中--另一个是 * they * name,也就是说,they 在 * they * 仓库中用于 * they * 分支的名称。
推送时,通常会看到以下两个名称的形式:例如git push origin master:master,意思是“打包我主文件中的内容,通过网络电话调用名为origin的远程文件,将包发送给他,并询问他是否将此文件作为master分支”。您还可以在左侧使用提交ID或单词HEADgit push origin HEAD:master意味着“接受我现在正在进行的任何提交,并请求远程origin将其作为他的master“。
当做git fetch时,两边会颠倒过来,通常还需要加上origin/(或者你的遥控器的名字)放在你想要的名字前面。也就是说,你得到了 hismaster,但是在 your 存储库中称之为origin/master。所以你得到了git fetch origin master:origin/master,4.如果你使用git fetch origin master:master,你将(潜在地)抹去你在自己母版上所做的工作。5
fetchpull还有一个奇怪的地方。我说过这是refspec的“第二简单”形式。最简单的就是像master这样的简单名称。它的 * 含义 * 取决于你在做什么:对于fetch,它意味着“把他的master带过来,但不必在我的本地存储库中给予它 * 任何 * 名称,只需保存散列ID”。对于push,它意味着“把我的master给他,并请他称之为master“。
同样,在旧版本的git中,如果你让git fetch把它们的master带过来(也可能是其他的),如果不给fetch一个本地名称来使用它,它将 * 只 * 保存ID(以及分支的名称)在Git的FETCH_HEAD文件中。(1.8.4及更高版本)中,git使用fetch =配置条目来确定要更新的远程跟踪分支。

丑陋的:git pull origin master branch(不执行)

如果你让git fetch带几个分支过来,它会正常工作(Git 1.8.4或更高版本);但如果你让git pull带几个分支过来,它就会表现得很糟糕。
fetch步骤工作正常,merge步骤出错。

pull代码要求git merge将多个分支合并到当前分支中,Git称之为“octopus merge”,除非你喜欢高级分支,否则你肯定不想这样做,所以不要这样做。
底线
我建议先执行一个git fetch操作,默认情况下它会把所有的都带过来,然后再执行单独的git mergegit rebase操作,这样你就能看到你在做什么了。
1或者git rebase,如果这样配置或指示的话。重定基通常比合并好,尽管它总是取决于细节。我的建议是首先使用git fetch,然后作为单独的步骤来做你自己的git rebasegit merge,至少当你是Git的新手的时候。我认为这样做实际上 * 更少 * 混乱,尽管您必须输入两个命令而不是一个。
2从技术上讲,它是指远程配置中fetch =行的内容,远程origin的正常行读取fetch = +refs/heads/*:refs/remotes/origin/*,这就是git知道如何将origin的分支重命名为您的origin/*whatever*分支的原因。
3从技术上讲,Git只使用一个原始哈希ID,保存在一个名为FETCH_HEAD的文件中。这里引号中的术语 *remote分支 * 是标准的Git术语:通过git fetch命令向Git提供提交的仓库上的分支名称。
4我还遗漏了一件事,那就是前导符号+:当获取“他们的主”时,你通常想要忘记你之前对“他们的主”的任何想法,所以fetch =行有那个前导加号。这打开了“强制”标志,即更新,即使它不是一个快进操作。fetch =行还完整地拼写出所有内容以避免问题,如果你不小心命名了一个本地分支origin/something,并且使用*字符来匹配多个分支名称。
5如果你真的把自己的工作搞砸了,你几乎总是可以把它找回来。Git真的试图把所有东西都保留至少30天。不过我们会把“如何把它找回来”留给其他SO条目。

yvfmudvl

yvfmudvl2#

不,git-pull只会合并to your local branch的修改,如果你想要其他分支的更新,你必须 checkout 它们,然后pull单独下载它们的更新。

vc9ivgsu

vc9ivgsu3#

您可以使用git pull --all拉取所有被跟踪的远程分支,也可以使用git fetch --all获取它们,然后再决定如何继续。请注意,pull 通常会自动合并任何更改,而这很少是您想要的。

yshpjwxd

yshpjwxd4#

否,仅将合并更改拉入到当前本地分支。
根据https://stackoverflow.com/a/59793998/14557599的答案,我在/etc/bash.bashrc中添加了一个函数来实现这一点:

git_pull() {
    echo - pulling all tracked local branches from "origin" remote
    orig_branch=$(git branch | grep "*" | sed "s/[ *]*//") # getting name of current branch via asterisk
    git fetch | return 1
    for branch in $(git branch | sed "s/[ *]*//") ; do # remove spaces and asterisk
        git checkout $branch && git merge --ff-only FETCH_HEAD
    done
    echo - checking out to branch where function was called from 
    git checkout $orig_branch
}; export -f git_pull

相关问题