Git中的FETCH_HEAD是什么意思?


220

git pull --help 说:

在其默认模式下,git pull是的缩写,git fetch后跟git merge FETCH_HEAD

这是FETCH_HEAD什么,在合并过程中实际上合并了git pull什么?


3
注意:从git 1.8.4(2013年8月)开始,git fetch origin master实际上将进行更新origin/master,而不仅仅是FETCH_HEAD。参见stackoverflow.com/a/20967347/6309
VonC 2014年

有关更多信息git merge FETCH_HEAD(自Git 2.5,2015年第二季度开始),请参见stackoverflow.com/a/30425991/6309
VonC

Answers:


218

FETCH_HEAD是一个短暂的ref,用于跟踪刚刚从远程存储库中获取的内容。git pull首先调用git fetch,通常情况下是从远程获取分支;FETCH_HEAD指向此分支的尖端(就像分支一样,它存储提交的SHA1)。git pull然后调用git merge,合并FETCH_HEAD到当前分支中。

结果正是您所期望的:适当的远程分支顶端的提交已合并到当前分支顶端的提交。

这有点像git fetch没有参数(或git remote update),更新所有远程分支,然后运行git merge origin/<branch>,但是在FETCH_HEAD内部使用它来引用所获取的任何单个引用,而无需命名。


9
@Jefromi:对不起,我想你就错了:据我了解,git fetch更新(合并)从远程存储,不只是所有的对象数据一个早午餐。因此,我无法从您的回答中理解git如何决定指向哪个分支的尖端FETCH_HEAD。我也不能FETCH_HEAD在git文档中找到(定义,而不是示例)。在FETCH_HEAD我看来,外观的存在更像是一种变通办法,以某种方式进行git pull工作。
阿列克谢

14
Alexey:FETCH_HEAD对应branch.<BRANCH>.merge于本地存储库配置中指定的远程分支的提示。因此,尽管fetch确实从远程存储中获取了所有对象数据,但仍FETCH_HEAD用于指示本地分支跟踪的远程分支已前进到何处。因此,如果您在本地master分支上并运行git fetch,并branch.master.merge指向refs/heads/master,则FETCH_HEAD其值将origin/master与获取操作后立即相同。
larsk's

4
@alexy FETCH_HEAD在其手册页的git fetch描述的第二段中进行了描述。我的回答是正确的。且不带参数的git fetch确实会更新默认远程的所有远程分支...但这绝对与合并不同。
卡斯卡贝尔2012年

4
什么是FETCH_HEAD如果你通过获取所有远程分支机构git fetch -a
斯蒂吉,2012年

2
@stigi您当前签出的分支在git config中指向的远程跟踪分支的尖端。请在上面的评论中查看larsks的答案。
Ankur Agarwal,2015年

19

FETCH_HEAD是对最后一次提取的提示的引用,无论该提取是直接使用fetch命令启动还是作为提取的一部分启动。FETCH_HEAD的当前值存储在.git名为的文件中的文件夹中FETCH_HEAD

因此,如果我发出:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD可能包含

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

如果我已将远程仓库配置为远程跟踪分支,则可以将跟踪分支合并到获取中。如果不这样做,则可以直接使用FETCH_HEAD合并最后一次获取的提示。

git merge FETCH_HEAD

1
再加上我的5美分。令我感到困惑的是,即使进行了新的提取操作(返回“无更改”)(日食),我的FETCH_HEAD仍在最新的提交之后。我认为原因是,自上次获取以来的所有更改均来自我自己,并已由我推送到服务器。因此,后续的获取操作无关,甚至都没有更新FETCH_HEAD。我不确定这是否是GIT或Eclipse Git实现的缺点。
Torge

11

乔纳森的答案中所述,FETCH_HEAD对应于file .git/FETCH_HEAD。通常,文件如下所示:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

注意如何标记除一个分支以外的所有分支not-for-merge。单数出局是在提取之前签出的分支。总结:FETCH_HEAD本质上对应于当前已签出的分支的远程版本。


9

我刚刚发现并使用过FETCH_HEAD。我想要从服务器上获取某些软件的本地副本,但我确实

git fetch gitserver release_1

gitserver是我存储git存储库的机器的名称。 release_1是该软件版本的标签。令我惊讶的release_1是,那时在我的本地计算机上找不到任何地方。我必须输入

 git tag release_1 FETCH_HEAD 

完成从远程存储库到本地存储库的带标记的提交链(release_1)的副本。Fetch找到了远程标记,将提交复制到了我的本地计算机,没有创建本地标记,但是将其设置FETCH_HEAD为提交的值,以便我可以找到并使用它。然后FETCH_HEAD,我用来创建一个与遥控器上的标签匹配的本地标签。这是什么FETCH_HEAD是什么以及如何使用它的实用说明,可能对其他人感到奇怪,为什么git fetch不能达到您天真的期望那样有用。

在我看来,最好避免这样做,而实现我正在尝试做的更好的方法是

git fetch gitserver release_1:release_1

例如,获取release_1并在本地将其称为release_1。(它是来源:dest,请参阅https://git-scm.com/book/en/v2/Git-Internals-The-Refspec;以防万一,您想给它起一个不同的名字!)

您可能FETCH_HEAD有时还是想使用:-

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

可能是在您的Git服务器上使用错误修复号1234的一种好方法,并且在将修复程序挑选到当前分支后,将Git的垃圾回收从服务器中丢弃副本。(我假设服务器上有一个不错的干净标记的提交,其中包含整个错误修复!)


有趣的反馈。+1
VonC

谢谢。我编辑了几年前第一次发现FETCH_HEAD时写的原始文章,因为它似乎鼓励使用FETCH_HEAD而不是refspecs的source:dest语法复制标签。希望我现在给出了一个更好的示例,说明如何使用FETCH_HEAD。
伊万

3

git pull是先获取再合并的组合。发生git fetch时,它会记下它在FETCH_HEAD中获取的内容的头提交(只是.git中具有该名称的文件),然后将这些提交合并到您的工作目录中。


3
@manjolds,“ 所获取内容的头提交”是什么意思?Git通过获取来获取所有内容。
阿列克谢

@Alexey,来自git手册:git-scm.com/docs/git-fetch将获取的ref的名称以及它们指向的对象名称写入.git / FETCH_HEAD
PJ_Finnegan,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.