Git FETCH_HEAD 短暂引用

3
  1. 我在这里读到,git FETCH_HEAD 是一个短期引用。git FETCH_HEAD 引用的寿命是多长?

  2. 当我执行 git fetch origin 命令时,在这种情况下许多远程跟踪分支都会被更新。FETCH_HEAD 会指向哪里?


1
那是两个问题。 - jub0bs
2个回答

5
  1. 它实际上根本不是一个真正的引用;引用是指向单个提交的指针(或者在HEAD的情况下,是一个分支名称)。相反,FETCH_HEAD是有关上次获取的分支的git元数据。它一直存在,直到被另一个获取覆盖。

  2. 它不是一个真正的引用,并包含有关已获取的远程跟踪信息的所有信息。

当您运行git merge FETCH_HEAD(或通过运行git pull隐式运行),git会将其视为特殊情况,而不是普通引用。相反,将查阅FETCH_HEAD文件,并查找未赋予特殊标记not-for-merge的分支。该分支将用于合并。(Git基于对应于您的git fetch调用的远程跟踪分支或运行它时所在的分支来确定此分支。)

请注意,在FETCH_HEAD中,还包括有关远程分支的详细信息,这使得git可以为合并提交创建消息,其中详细说明了该分支来自何处。(例如,“Merge of branch 'master' of https://my.visualstudio.com/my/repository”)。

FETCH_HEAD,就像git存储库元数据的许多其他部分一样,只是一个文本文件;阅读它以查看每次获取后如何更改非常有启发性。(例如,您可以看到,您链接的答案非常不正确,并且FETCH_HEAD不包含单个分支的信息,而是包含远程上所有分支的信息。)


HEAD的情况下,是一个分支名称。那么脱离HEAD状态呢? - jub0bs
据我所读,git pull origin master会先进行拉取(fetch)操作,然后再执行合并(merge)。在执行合并时,它会执行git merge FETCH_HEAD指令。如果FETCH_HEAD包含有关已获取的所有分支的元数据,则为什么git pull要使用FETCH_HEAD来执行合并呢?https://git-scm.com/docs/git-pull - Number945
2
是的,你说得对,这正是 git pull 所做的。FETCH_HEAD 包括制表符分隔的字段,其中一个字段指示应合并哪个获取的分支。(要合并的分支具有值为 for-merge 的字段,在所有其他分支中将为空。)git merge FETCH_HEAD 特别解决了这个信息,并不像处理普通分支一样处理 FETCH_HEAD - Edward Thomson
请原谅,我搞反了。除一个以外,其余都会标记为 不合并 - Edward Thomson
所以,我们不能称呼git fetch_head引用。这个实体叫什么?我应该只说fetch_head是我的git目录中的一个文件吗? - Number945
是的,如果你需要一个描述,那就是正确的。 - Edward Thomson

2
根据gitrevisionsFETCH_HEAD记录了你上一次使用git fetch从远程仓库获取的分支。第一次git fetch会创建FETCH_HEAD文件,并且之后每次git fetch都会更新它。这里的git fetch也包括git pull,因为git pull可以是git fetch + git merge或者git fetch + git rebase
对于git fetch origin fooFETCH_HEAD指向foo分支的最新提交。如果uploadpack.allowTipSHA1InWant在远程仓库中设置为true,则foo可以是特定对象(提交、树、blob或标签)的哈希值,此时FETCH_HEAD将指向该对象。
当涉及到git fetchgit fetch origin时,情况就变得复杂起来。那么FETCH_HEAD会被更新到哪个位置呢?这取决于很多情况,如本地仓库是否处于分离头状态、是否在具有上游的特定分支上、是否在没有上游的分支上或其他情况。如果不深入挖掘,我们可以从git fetch的输出结果中了解到更新后的位置。以下是一个示例:
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 7), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From D:/hello
   ca2d63e..38d365c  ost        -> origin/ost
 * [new branch]      a          -> origin/a
   8fe4b12..db5a0d9  aaa        -> origin/aaa
   36ca690..e00229b  haha       -> origin/haha
   c96b459..5ab6097  master     -> origin/master
   283a081..004375e  mist       -> origin/mist

我们可以看到输出结果显示了哪些引用被git fetch更新。 FETCH_HEAD总是指向第一个引用的末端。在这个示例中,FETCH_HEADorigin/ost的末端,38d365c。当仅获取一个引用或一个对象时,这也是正确的。
如果git fetch过程失败,FETCH_HEAD将变成未知的修订版本。文件.git/FETCH_HEAD仍然存在,但是它是空的。

Git是如何决定FETCH_HEAD指向origin/ost的呢?如果有人执行git pull origin,这不是很危险吗?因为我们永远不知道会合并什么。 - Number945
1
@BreakingBenjamin 当没有指定特定的引用时,Git只是从一些事实中推断。在我的示例中,本地仓库就在分支ost上,它的跟踪分支是origin/ost,因此它知道应该更新和合并上游,因此FETCH_HEAD指向origin/ost。如果它处于分离的HEAD或另一个没有上游的分支中,FETCH_HEAD将指向origin/a,因为它是按字母顺序排列的第一个,接下来的git mergegit rebase将会失败以避免危险。 - ElpieKay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接