git pull --help
说:
在其默认模式下,
git pull
是git fetch
后跟的简写git merge FETCH_HEAD
。
这是FETCH_HEAD
什么以及在 期间实际合并了git pull
什么?
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
在内部使用而不是引用获取的任何单个 ref,而不是需要命名。
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
正如乔纳森的回答中提到的, 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 本质上对应于当前签出的分支的远程版本。
我刚刚发现并使用了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 的垃圾收集处理来自服务器的副本。(我假设有一个漂亮的干净标记提交,其中包含服务器上的整个错误修复!)
git pull 是 fetch 和 merge 的组合。当 git fetch 发生时,它会记录它在 FETCH_HEAD 中获取的内容的头部提交(只是 .git 中具有该名称的文件),然后这些提交将合并到您的工作目录中。
FETCH_HEAD
是一个短暂的 ref,用于跟踪刚刚从远程存储库中获取的内容。
实际上,......并不总是考虑到这一点,在 Git 2.29(2020 年第四季度)中,“ git fetch
” (man)学会--no-write-fetch-head
了避免写入FETCH_HEAD
文件的选项。
请参阅Junio C Hamano ( ) 的提交 887952b(2020 年 8 月 18 日)。(由Junio C Hamano 合并 -- --在提交 b556050中,2020 年 8 月 24 日)gitster
gitster
fetch
:可选地允许禁用FETCH_HEAD
更新签字人:Derrick Stolee
如果您运行 fetch 但将结果记录在远程跟踪分支中,或者您对获取的 refs 不做任何事情(例如,您只是镜像),或者您总是从远程跟踪 refs 工作(例如,您获取然后
origin/branchname
单独合并),你可以完全没有FETCH_HEAD
。教“
git fetch
” (man)一个命令行选项“--[no-]write-fetch-head
”。
- 默认值为 write
FETCH_HEAD,
并且该选项主要用于与“--no-
”前缀一起使用以覆盖此默认值,因为没有匹配fetch.writeFetchHEAD
的配置变量可以将默认值翻转为关闭(在这种情况下,可能需要正数形式来击败它)。注意,在“
--dry-run
”模式下,FETCH_HEAD
永远不会被写入;否则你会在文件中看到你实际上没有的对象列表。传递
--write-fetch-head
不会强制[
git fetch](https://github.com/git/git/blob/887952b8c680626f4721cb5fa57704478801aca4/Documentation/git-fetch.txt)<sup>([man](https://git-scm.com/docs/git-fetch))</sup>
写入文件。
fetch-options
现在在其手册页中包含:
--[no-]write-fetch-head
FETCH_HEAD
将在文件中直接获取的远程引用列表写入$GIT_DIR
.
这是默认设置。
--no-write-fetch-head
从命令行传递告诉 Git 不要写入文件。
在--dry-run
选项下,文件永远不会被写入。
还要考虑一下,仍然使用 Git 2.29(2020 年第四季度),FETCH_HEAD
现在总是从文件系统中读取,而不管使用的 ref 后端如何,因为它的格式比普通 refs 丰富得多,并且直接由“ git fetch
” (man)作为纯文件..
请参阅Han-Wen Nienhuys ( ) 的commit e811530、commit 5085aef、commit 4877c6c、commit e39620f(2020 年 8 月 19 日)。(由Junio C Hamano 合并——在提交 98df75b中,2020 年 8 月 27 日)hanwen
gitster
refs
:阅读FETCH_HEAD
和MERGE_HEAD
一般签字人:Han-Wen Nienhuys
和refs 必须存储在文件中,无论 ref 后端的类型如何
FETCH_HEAD
。这是因为它们可以容纳的不仅仅是一个 ref。MERGE_HEAD
要将它们容纳为备用 ref 后端,请从
refs_read_raw_ref()
.
在 Git 2.29(2020 年第四季度)中,更新了延迟克隆存储库中的按需获取代码。
请参阅提交 db3c293(2020 年 9 月 2 日)和提交 9dfa8db、提交 7ca3c0a、提交 5c3b801、提交 abcb7ee、提交 e5b9421、提交 2b713c2、提交 cbe566a(2020 年 8 月 17 日),作者:Jonathan Tan ( jhowtan
)。
(由Junio C Hamano 合并 -- gitster
--在提交 b4100f3中,2020 年 9 月 3 日)
fetch
:FETCH_HEAD
如果 --no-write-fetch-head 不显示签字人:Jonathan Tan
887952b8c6(“
fetch
:可选地允许禁用FETCH_HEAD
更新”,2020 年 8 月 18 日,Git v2.29.0 -批次 #10中列出的合并)引入了在获取期间禁用写入的能力,但没有抑制“当此能力为用过的。FETCH_HEAD
<source> -> FETCH_HEAD"
在这种情况下,此消息具有误导性,因为
FETCH_HEAD
未写入。此外,由于“
fetch
”用于延迟获取部分克隆中丢失的对象,因此在这种情况下,这会显着混淆输出,因为要获取的对象可能很多。因此,在传递时抑制此消息
--no-write-fetch-head
(但不是在--dry-run
设置时)。
我只是想拉下一个(补丁)分支,它是通过直接从 GitHub 进行更改而创建的。该分支仅出现在 GH 上。当我尝试做 ag pull 时,分支没有出现。
我能够使用以下方法签出分支:
git fetch origin pull/2/head
git checkout -b <desired-branch-name> FETCH_HEAD