Git拉——帮助说:

在默认模式下,git pull是git fetch的简写,后面跟着git merge FETCH_HEAD。

FETCH_HEAD是什么? git拉取过程中合并了什么?


当前回答

Git pull是一个fetch和merge的组合。当git获取发生时,它会注意到它在FETCH_HEAD中获取的内容的头提交(只是一个在.git中同名的文件),然后这些提交被合并到你的工作目录中。

其他回答

Git pull是一个fetch和merge的组合。当git获取发生时,它会注意到它在FETCH_HEAD中获取的内容的头提交(只是一个在.git中同名的文件),然后这些提交被合并到你的工作目录中。

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

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

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

FETCH_HEAD是一个短命的引用,用于跟踪刚刚从远程存储库获取的内容。

实际上,…并不总是考虑到这一点,在Git 2.29 (Q4 2020)中,“Git fetch”(man)学会了—no-write-fetch-head选项,以避免写入FETCH_HEAD文件。

参见juno C Hamano (gitster)提交的887952b(2020年8月18日)。 (由Junio C Hamano—gitster—在commit b556050中合并,2020年8月24日)

fetch:可选允许禁用FETCH_HEAD更新 署名:Derrick Stolee

If you run fetch but record the result in remote-tracking branches, and either if you do nothing with the fetched refs (e.g. you are merely mirroring) or if you always work from the remote-tracking refs (e.g. you fetch and then merge origin/branchname separately), you can get away with having no FETCH_HEAD at all. Teach "git fetch"(man) a command line option "--[no-]write-fetch-head". The default is to write FETCH_HEAD, and the option is primarily meant to be used with the "--no-" prefix to override this default, because there is no matching fetch.writeFetchHEAD configuration variable to flip the default to off (in which case, the positive form may become necessary to defeat it). Note that under "--dry-run" mode, FETCH_HEAD is never written; otherwise you'd see list of objects in the file that you do not actually have. Passing --write-fetch-head does not force [git fetch](https://github.com/git/git/blob/887952b8c680626f4721cb5fa57704478801aca4/Documentation/git-fetch.txt)<sup>([man](https://git-scm.com/docs/git-fetch))</sup> to write the file.

Fetch-options现在包含在它的手册页中:

——不——write-fetch-head 直接在$GIT_DIR下写入FETCH_HEAD文件中获取的远程引用列表。 这是默认值。 从命令行传递——no-write-fetch-head告诉 Git不写文件。 在——dry-run选项下,文件永远不会被写入。


再考虑一下,仍然使用Git 2.29 (Q4 2020), FETCH_HEAD现在总是从文件系统中读取,而不管使用的是ref后端,因为它的格式比普通的ref丰富得多,并且直接由“Git fetch”(man)作为一个普通文件写入。

参见hanwen Nienhuys (hanwen)的commit e811530, commit 5085aef, commit 4877c6c, commit e39620f (19 Aug 2020)。 (由Junio C Hamano—gitster—在commit 98df75b中合并,2020年8月27日)

参考:读取FETCH_HEAD和MERGE_HEAD一般 签署人:Han-Wen Nienhuys

FETCH_HEAD和MERGE_HEAD引用必须存储在文件中,无论引用后端是什么类型。这是因为它们可以容纳不止一个裁判。 为了将它们用于备用的ref后端,一般从refs_read_raw_ref()中的文件中读取它们。


在Git 2.29 (Q4 2020)中,更新到惰性克隆存储库中的按需抓取代码。

参见Jonathan Tan (jhowtan)的commit db3c293 (02 Sep 2020), and commit 9dfa8db, commit 7ca3c0a, commit 5c3b801, commit abcb7ee, commit e5b9421, commit 2b713c2, commit cbe566a (2020 Aug 17)。 (由Junio C Hamano - gitster - in commit b4100f3, 03 Sep 2020)

fetch:不显示FETCH_HEAD如果——no-write-fetch-head 署名:乔纳森·谭

887952b8c6 ("fetch: optionally allow disabling FETCH_HEAD update", 2020-08-18, Git v2.29.0 -- merge listed in batch #10) introduced the ability to disable writing to FETCH_HEAD during fetch, but did not suppress the "<source> -> FETCH_HEAD" message when this ability is used. This message is misleading in this case, because FETCH_HEAD is not written. Also, because "fetch" is used to lazy-fetch missing objects in a partial clone, this significantly clutters up the output in that case since the objects to be fetched are potentially numerous. Therefore, suppress this message when --no-write-fetch-head is passed (but not when --dry-run is set).

我刚刚发现并使用了FETCH_HEAD。我想从服务器上获得一些软件的本地副本,我做到了

git fetch gitserver release_1

Gitserver是存储git存储库的机器的名称。 Release_1是软件版本的标记。令我惊讶的是,在我的本地机器上找不到release_1。我必须打字

 git tag release_1 FETCH_HEAD 

to complete the copy of the tagged chain of commits (release_1) from the remote repository to the local one. Fetch had found the remote tag, copied the commit to my local machine, had not created a local tag, but had set FETCH_HEAD to the value of the commit, so that I could find and use it. I then used FETCH_HEAD to create a local tag which matched the tag on the remote. That is a practical illustration of what FETCH_HEAD is and how it can be used, and might be useful to someone else wondering why git fetch doesn't do what you would naively expect.

在我看来,为了达到这个目的,最好避免这样做,而实现我想要做的更好的方法是

git fetch gitserver 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服务器上使用bug修复号1234可能是一个很好的方法,并且一旦修复被选中到你当前的分支上,让Git的垃圾收集来处理服务器上的副本。(我假设在服务器上有一个干净的标记提交,包含了整个错误修复!)

正如Jonathan的回答中提到的,FETCH_HEAD对应于文件.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本质上对应于当前签出的分支的远程版本。