English ▾ 主题 ▾ 最新版本 ▾ git-fetch 最近更新于 2.48.0

名称

git-fetch - 从另一个仓库下载对象和引用

概要

git fetch [<options>] [<repository> [<refspec>…​]]
git fetch [<options>] <group>
git fetch --multiple [<options>] [(<repository> | <group>)…​]
git fetch --all [<options>]

描述

从一个或多个其他仓库抓取分支和/或标签(统称为 “引用”),以及完成它们历史记录所需的对象。远程跟踪分支会更新(请参阅下面 <refspec> 的描述,了解控制此行为的方法)。

默认情况下,任何指向正在抓取的历史记录中的标签也会被抓取;效果是抓取指向你感兴趣的分支的标签。可以使用 --tags 或 --no-tags 选项或通过配置 remote.<name>.tagOpt 更改此默认行为。通过使用显式抓取标签的引用规范,你可以抓取未指向你感兴趣的分支的标签。

如果给定了 <group> 并且配置文件中存在 remotes.<group> 条目,git fetch 可以从单个命名仓库或 URL 抓取,也可以一次从多个仓库抓取。(参见 git-config[1])。

当未指定远程仓库时,默认情况下将使用 origin 远程仓库,除非为当前分支配置了上游分支。

抓取的引用的名称以及它们指向的对象名称会写入 .git/FETCH_HEAD。此信息可供脚本或其他 git 命令使用,例如 git-pull[1]

选项

--[no-]all

抓取所有远程仓库,除了那些设置了 remote.<name>.skipFetchAll 配置变量的远程仓库。 这将覆盖配置变量 fetch.all`。

-a
--append

将抓取的引用的引用名称和对象名称附加到 .git/FETCH_HEAD 的现有内容中。如果没有此选项,.git/FETCH_HEAD 中的旧数据将被覆盖。

--atomic

使用原子事务来更新本地引用。要么更新所有引用,要么在出错时,不更新任何引用。

--depth=<depth>

将抓取限制为从每个远程分支历史记录的顶部开始指定数量的提交。 如果抓取到由 git clone 使用 --depth=<depth> 选项创建的仓库(请参阅 git-clone[1]),则将历史记录加深或缩短为指定数量的提交。 不会抓取加深提交的标签。

--deepen=<depth>

与 --depth 类似,只是它指定从当前浅边界开始的提交数,而不是从每个远程分支历史记录的顶部开始。

--shallow-since=<date>

加深或缩短浅仓库的历史记录,以包含 <date> 之后所有可访问的提交。

--shallow-exclude=<ref>

加深或缩短浅仓库的历史记录,以排除从指定的远程分支或标签可访问的提交。 可以多次指定此选项。

--unshallow

如果源仓库是完整的,则将浅仓库转换为完整仓库,删除浅仓库施加的所有限制。

如果源仓库是浅的,则尽可能多地抓取,以便当前仓库具有与源仓库相同的历史记录。

--update-shallow

默认情况下,从浅仓库抓取时,git fetch 拒绝需要更新 .git/shallow 的引用。 此选项更新 .git/shallow 并接受此类引用。

--negotiation-tip=<commit|glob>

默认情况下,Git 会向服务器报告从所有本地引用可访问的提交,以查找公共提交,从而尝试减小要接收的包文件的大小。 如果指定,Git 将仅报告从给定提示可访问的提交。 当用户知道哪个本地引用可能与要抓取的上游引用有公共提交时,这对于加快抓取速度很有用。

可以多次指定此选项; 如果是这样,Git 将报告从任何给定提交可访问的提交。

此选项的参数可以是引用名称上的 glob,一个引用,或提交的(可能缩写的)SHA-1。 指定 glob 相当于多次指定此选项,每个匹配的引用名称一次。

另请参阅 git-config[1] 中记录的 fetch.negotiationAlgorithmpush.negotiate 配置变量,以及下面的 --negotiate-only 选项。

--negotiate-only

不要从服务器抓取任何内容,而是打印我们在服务器上提供的 --negotiation-tip=* 参数的祖先。

这与 --recurse-submodules=[yes|on-demand] 不兼容。 在内部,这用于实现 push.negotiate 选项,请参见 git-config[1]

--dry-run

显示将要执行的操作,而不进行任何更改。

--porcelain

以易于脚本解析的格式将输出打印到标准输出。 有关详细信息,请参见 git-fetch[1] 中的 OUTPUT 部分。

这与 --recurse-submodules=[yes|on-demand] 不兼容,并且优先于 fetch.output config 选项。

--[no-]write-fetch-head

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

-f
--force

git fetch<src>:<dst> 引用规范一起使用时,它可能会拒绝更新本地分支,如下面的 <refspec> 部分中所述。 此选项会覆盖该检查。

-k
--keep

保留下载的包。

--multiple

允许指定多个 <repository> 和 <group> 参数。 不得指定任何 <refspec>。

--[no-]auto-maintenance
--[no-]auto-gc

在最后运行 git maintenance run --auto 以在需要时执行自动仓库维护。 (--[no-]auto-gc 是一个同义词。) 默认情况下启用此选项。

--[no-]write-commit-graph

抓取后写入提交图。 这会覆盖配置设置 fetch.writeCommitGraph

--prefetch

修改配置的引用规范,以将所有引用放入 refs/prefetch/ 命名空间中。 请参阅 git-maintenance[1] 中的 prefetch 任务。

-p
--prune

在抓取之前,删除远程仓库上不再存在的任何远程跟踪引用。 如果仅由于默认标签自动跟随或由于 --tags 选项而抓取标签,则标签不受修剪的约束。 但是,如果由于显式引用规范而抓取标签(无论是在命令行上还是在远程配置中,例如,如果使用 --mirror 选项克隆了远程仓库),则它们也受修剪的约束。 提供 --prune-tags 是提供标签引用规范的简写形式。

有关更多详细信息,请参见下面的 PRUNING 部分。

-P
--prune-tags

如果启用了 --prune,则在抓取之前,删除远程仓库上不再存在的任何本地标签。 应该更小心地使用此选项,与 --prune 不同,它将删除已创建的任何本地引用(本地标签)。 此选项是提供显式标签引用规范以及 --prune 的简写形式,请参见其文档中的讨论。

有关更多详细信息,请参见下面的 PRUNING 部分。

-n
--no-tags

默认情况下,会获取并本地存储指向从远程仓库下载的对象的标签。此选项禁用此自动标签跟踪。可以使用 remote.<name>.tagOpt 设置来指定远程仓库的默认行为。请参阅 git-config[1]

--refetch

此选项会像全新克隆一样获取所有对象,而不是与服务器协商以避免传输本地已存在的提交和关联对象。当配置中的部分克隆过滤器或使用 --filter= 的过滤器定义已更改时,请使用此选项重新应用。自动的获取后维护将执行对象数据库打包合并,以删除任何重复对象。

--refmap=<refspec>

当获取命令行上列出的引用时,使用指定的引用规范(可以多次给出)将引用映射到远程跟踪分支,而不是远程仓库的 remote.*.fetch 配置变量的值。为 --refmap 选项提供一个空的 <refspec> 会导致 Git 忽略配置的引用规范,而完全依赖于作为命令行参数提供的引用规范。有关详细信息,请参阅“配置的远程跟踪分支”部分。

-t
--tags

从远程仓库获取所有标签(即,将远程标签 refs/tags/* 获取到具有相同名称的本地标签),以及其他通常会被获取的内容。单独使用此选项不会导致标签被修剪,即使使用了 --prune 也是如此(尽管如果标签也是显式引用规范的目标,则可能会被修剪;请参阅 --prune)。

--recurse-submodules[=(yes|on-demand|no)]

此选项控制是否以及在什么条件下也应获取子模块的新提交。在递归遍历子模块时,git fetch 始终尝试获取“已更改”的子模块,也就是说,子模块具有新获取的父项目提交所引用的提交,但本地子模块克隆中缺少这些提交。只要本地存在已更改的子模块(例如在 $GIT_DIR/modules/ 中),就可以获取该子模块(请参阅 gitsubmodules[7]);如果上游添加了一个新的子模块,则只有通过 git submodule update 等命令克隆该子模块后才能获取它。

当设置为 *on-demand* 时,仅获取已更改的子模块。当设置为 *yes* 时,获取所有已填充的子模块,并获取未填充和已更改的子模块。当设置为 *no* 时,永远不会获取子模块。

如果未指定,则使用 fetch.recurseSubmodules 的值(如果已设置)(请参阅 git-config[1]),如果未设置,则默认为 *on-demand*。当不带任何值使用此选项时,它默认为 *yes*。

-j
--jobs=<n>

用于所有形式的获取的并行子进程的数量。

如果指定了 --multiple 选项,则会并行获取不同的远程仓库。如果获取多个子模块,它们也会并行获取。要独立控制它们,请使用配置设置 fetch.parallelsubmodule.fetchJobs(请参阅 git-config[1])。

通常,并行递归和多远程获取会更快。默认情况下,获取是按顺序执行的,而不是并行执行的。

--no-recurse-submodules

禁用子模块的递归获取(这与使用 --recurse-submodules=no 选项的效果相同)。

--set-upstream

如果成功获取远程仓库,则添加上游(跟踪)引用,供无参数的 git-pull[1] 和其他命令使用。有关更多信息,请参阅 git-config[1] 中的 branch.<name>.mergebranch.<name>.remote

--submodule-prefix=<path>

将 <path> 添加到信息性消息中打印的路径之前,例如“Fetching submodule foo”。当递归遍历子模块时,此选项在内部使用。

--recurse-submodules-default=[yes|on-demand]

此选项在内部用于临时为 --recurse-submodules 选项提供一个非负默认值。配置 fetch 的子模块递归的所有其他方法(例如 gitmodules[5]git-config[1] 中的设置)会覆盖此选项,直接指定 --[no-]recurse-submodules 也是如此。

-u
--update-head-ok

默认情况下,git fetch 拒绝更新与当前分支对应的 head。此标志禁用此检查。这纯粹是为了 git pullgit fetch 通信的内部用途,除非您正在实现自己的 Porcelain,否则不应使用它。

--upload-pack <upload-pack>

当给出此选项,并且要从中获取的仓库由 git fetch-pack 处理时,--exec=<upload-pack> 会传递给该命令,以指定在另一端运行的命令的非默认路径。

-q
--quiet

将 --quiet 传递给 git-fetch-pack 并静默任何其他内部使用的 git 命令。进度不会报告到标准错误流。

-v
--verbose

显示详细信息。

--progress

默认情况下,当标准错误流连接到终端时,会在标准错误流上报告进度状态,除非指定了 -q。即使标准错误流未定向到终端,此标志也会强制显示进度状态。

-o <option>
--server-option=<option>

在使用协议版本 2 进行通信时,将给定的字符串传输到服务器。给定的字符串不能包含 NUL 或 LF 字符。服务器对服务器选项的处理(包括未知选项)是服务器特定的。当给出多个 --server-option=<option> 时,它们会按照命令行上列出的顺序发送到另一端。当命令行上没有给出 --server-option=<option> 时,则使用配置变量 remote.<name>.serverOption 的值。

--show-forced-updates

默认情况下,git 会检查在获取期间是否强制更新了分支。可以通过 fetch.showForcedUpdates 禁用此功能,但 --show-forced-updates 选项保证会进行此检查。请参阅 git-config[1]

--no-show-forced-updates

默认情况下,git 会检查在获取期间是否强制更新了分支。传递 --no-show-forced-updates 或将 fetch.showForcedUpdates 设置为 false 以跳过此检查,从而提高性能。如果在 *git-pull* 期间使用,--ff-only 选项仍然会检查强制更新,然后再尝试快速前进更新。请参阅 git-config[1]

-4
--ipv4

仅使用 IPv4 地址,忽略 IPv6 地址。

-6
--ipv6

仅使用 IPv6 地址,忽略 IPv4 地址。

<repository>

作为获取或拉取操作源的“远程”仓库。此参数可以是 URL(请参阅下面的 GIT URLS 部分)或远程仓库的名称(请参阅下面的 REMOTES 部分)。

<group>

一个名称,指代配置文件中 remotes.<group> 的值所表示的仓库列表。(请参阅 git-config[1])。

<refspec>

指定要获取哪些引用以及要更新哪些本地引用。当命令行上没有出现 <refspec> 时,要获取的引用将从 remote.<repository>.fetch 变量中读取(请参阅下面的 配置的远程跟踪分支)。

<refspec> 参数的格式是一个可选的加号 +,后跟源 <src>,后跟一个冒号 :,后跟目标 <dst>。当 <dst> 为空时,可以省略冒号。 <src> 通常是一个引用,或是一个带有单个 * 的 glob 模式,用于匹配一组引用,但它也可以是一个完全拼写的十六进制对象名称。

<refspec> 可以在其 <src> 中包含一个 *,以指示一个简单的模式匹配。这样的引用规范的作用类似于一个 glob,它可以匹配任何带有该模式的引用。模式 <refspec> 必须在 <src> 和 <dst> 中都有一个且只有一个 *。它将通过将 * 替换为从源匹配的内容,将引用映射到目标。

如果一个引用规范以 ^ 为前缀,它将被解释为负引用规范。这样的引用规范不是指定要获取哪些引用或要更新哪些本地引用,而是指定要排除的引用。如果一个引用至少匹配一个正引用规范,并且不匹配任何负引用规范,则认为该引用匹配。负引用规范对于限制模式引用规范的范围非常有用,这样它就不会包含特定的引用。负引用规范本身可以是模式引用规范。但是,它们只能包含 <src>,而不指定 <dst>。也不支持完全拼写的十六进制对象名称。

tag <tag>refs/tags/<tag>:refs/tags/<tag> 具有相同的含义;它请求获取给定标签之前的所有内容。

获取与 <src> 匹配的远程引用,并且如果 <dst> 不是空字符串,则尝试更新与其匹配的本地引用。

是否允许在没有 --force 的情况下进行该更新取决于它要获取到的引用命名空间、要获取的对象的类型,以及该更新是否被认为是快速前进。通常,与推送时应用的规则相同,有关这些规则的说明,请参阅 git-push[1]<refspec>... 部分。下面记录了 git fetch 特有的这些规则的例外情况。

直到 Git 版本 2.20,与使用 git-push[1] 进行推送不同,对 refs/tags/* 的任何更新都将被接受,而无需在引用规范中使用 +(或 --force)。在获取时,我们随意地认为来自远程仓库的所有标签更新都是强制获取。自 Git 版本 2.20 以来,获取以更新 refs/tags/* 的工作方式与推送时相同。也就是说,如果没有在引用规范中使用 +(或 --force),任何更新都将被拒绝。

与使用 git-push[1] 进行推送不同,对 refs/{tags,heads}/* 之外的任何更新都将被接受,而无需在引用规范中使用 +(或 --force),无论是交换树对象和 blob,还是交换提交和另一个没有前一个提交作为祖先的提交等。

与使用 git-push[1] 进行推送不同,没有任何配置可以修改这些规则,也没有类似于 pre-receive 钩子的 pre-fetch 钩子。

与使用 git-push[1] 进行推送类似,上述关于不允许作为更新的所有规则都可以通过在 refspec 前面添加可选的 + 符号(或使用 --force 命令行选项)来覆盖。唯一的例外是,无论如何强制,refs/heads/* 命名空间都不会接受非 commit 对象。

注意
当您想要拉取的远程分支已知会被定期回退和 rebase 时,其新的顶端(tip)将不会是其之前的顶端(上次拉取时存储在您的远程跟踪分支中的顶端)的后代。您应该使用 + 符号来表示此类分支需要非快进更新。没有办法确定或声明分支将以这种行为在存储库中提供;拉取用户只需知道这是分支的预期使用模式。
--stdin

除了作为参数提供的 refspec 外,还从 stdin 读取 refspec,每行一个。"tag <name>" 格式不受支持。

GIT URLS

通常,URL 包含关于传输协议、远程服务器地址和存储库路径的信息。根据传输协议,某些信息可能缺失。

Git 支持 ssh、git、http 和 https 协议(此外,ftp 和 ftps 可以用于拉取,但效率低下且已弃用;请勿使用)。

原生传输(即 git:// URL)不进行身份验证,应在不安全的网络上谨慎使用。

以下语法可以与它们一起使用

  • ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>

  • git://<host>[:<port>]/<path-to-git-repo>

  • http[s]://<host>[:<port>]/<path-to-git-repo>

  • ftp[s]://<host>[:<port>]/<path-to-git-repo>

另一种类似 scp 的语法也可以与 ssh 协议一起使用

  • [<user>@]<host>:/<path-to-git-repo>

仅当第一个冒号之前没有斜杠时,才识别此语法。这有助于区分包含冒号的本地路径。例如,本地路径 foo:bar 可以指定为绝对路径或 ./foo:bar,以避免被误解为 ssh URL。

ssh 和 git 协议还支持 ~<username> 扩展

  • ssh://[<user>@]<host>[:<port>]/~<user>/<path-to-git-repo>

  • git://<host>[:<port>]/~<user>/<path-to-git-repo>

  • [<user>@]<host>:~<user>/<path-to-git-repo>

对于本地存储库,Git 原生也支持以下语法

  • /path/to/repo.git/

  • file:///path/to/repo.git/

这两种语法基本等效,但在克隆时除外,前者意味着 --local 选项。请参阅 git-clone[1] 了解详细信息。

git clonegit fetchgit pull,但不包括 git push,也将接受合适的 bundle 文件。请参阅 git-bundle[1]

当 Git 不知道如何处理某种传输协议时,它会尝试使用 remote-<transport> 远程助手(如果存在)。要显式请求远程助手,可以使用以下语法

  • <transport>::<address>

其中 <address> 可以是路径、服务器和路径,或由特定远程助手识别的任意类似 URL 的字符串。请参阅 gitremote-helpers[7] 了解详细信息。

如果有大量名称相似的远程存储库,并且您想为它们使用不同的格式(这样您使用的 URL 将被重写为可以工作的 URL),您可以创建以下形式的配置部分

	[url "<actual-url-base>"]
		insteadOf = <other-url-base>

例如,使用以下配置:

	[url "git://git.host.xz/"]
		insteadOf = host.xz:/path/to/
		insteadOf = work:

像 "work:repo.git" 或 "host.xz:/path/to/repo.git" 这样的 URL 将在任何接受 URL 的上下文中被重写为 "git://git.host.xz/repo.git"。

如果只想重写推送的 URL,您可以创建以下形式的配置部分

	[url "<actual-url-base>"]
		pushInsteadOf = <other-url-base>

例如,使用以下配置:

	[url "ssh://example.org/"]
		pushInsteadOf = git://example.org/

像 "git://example.org/path/to/repo.git" 这样的 URL 将为推送重写为 "ssh://example.org/path/to/repo.git",但拉取仍然使用原始 URL。

REMOTES

以下名称之一可以代替 URL 用作 <repository> 参数

  • Git 配置文件中的 remote:$GIT_DIR/config

  • $GIT_DIR/remotes 目录中的文件,或

  • $GIT_DIR/branches 目录中的文件。

所有这些还允许您从命令行省略 refspec,因为它们每个都包含一个 git 默认使用的 refspec。

配置文件中的命名 remote

您可以选择提供先前使用 git-remote[1]git-config[1] 甚至通过手动编辑 $GIT_DIR/config 文件配置的 remote 的名称。此 remote 的 URL 将用于访问存储库。当您在命令行上未提供 refspec 时,将默认使用此 remote 的 refspec。配置文件中的条目如下所示

	[remote "<name>"]
		url = <URL>
		pushurl = <pushurl>
		push = <refspec>
		fetch = <refspec>

<pushurl> 仅用于推送。它是可选的,默认为 <URL>。推送到 remote 会影响所有定义的 pushurl 或所有定义的 url(如果未定义 pushurl)。但是,拉取只会从第一个定义的 url 中拉取(如果定义了多个 url)。

$GIT_DIR/remotes 中的命名文件

您可以选择提供 $GIT_DIR/remotes 中文件的名称。此文件中的 URL 将用于访问存储库。当您在命令行上未提供 refspec 时,将默认使用此文件中的 refspec。此文件应具有以下格式

	URL: one of the above URL formats
	Push: <refspec>
	Pull: <refspec>

Push: 行由 git push 使用,Pull: 行由 git pullgit fetch 使用。可以为其他分支映射指定多个 Push:Pull: 行。

$GIT_DIR/branches 中的命名文件

您可以选择提供 $GIT_DIR/branches 中文件的名称。此文件中的 URL 将用于访问存储库。此文件应具有以下格式

	<URL>#<head>

<URL> 是必需的;#<head> 是可选的。

根据操作,如果您未在命令行上提供 refspec,git 将使用以下 refspec 之一。<branch> 是此文件在 $GIT_DIR/branches 中的名称,<head> 默认为 master

git fetch 使用

	refs/heads/<head>:refs/heads/<branch>

git push 使用

	HEAD:refs/heads/<head>

配置的远程跟踪分支

您通常通过定期重复地从中拉取来与相同的远程存储库进行交互。为了跟踪此类远程存储库的进度,git fetch 允许您配置 remote.<repository>.fetch 配置变量。

通常,这样的变量可能如下所示

[remote "origin"]
	fetch = +refs/heads/*:refs/remotes/origin/*

此配置以两种方式使用

  • git fetch 运行时,未在命令行上指定要拉取的分支和/或标签,例如 git fetch origingit fetchremote.<repository>.fetch 值用作 refspec—​它们指定要拉取哪些引用以及要更新哪些本地引用。上面的示例将拉取 origin 中存在的所有分支(即任何匹配值的左侧的引用,refs/heads/*)并更新 refs/remotes/origin/* 层次结构中的相应远程跟踪分支。

  • git fetch 运行时,在命令行上指定了要拉取的显式分支和/或标签,例如 git fetch origin master,命令行上给出的 <refspec> 确定要拉取的内容(例如示例中的 master,它是 master: 的简写,后者又意味着“拉取 *master* 分支,但我没有明确说明要使用命令行中的哪个远程跟踪分支来更新它”),并且示例命令将 *仅* 拉取 *master* 分支。remote.<repository>.fetch 值确定要更新哪个远程跟踪分支(如果有)。以这种方式使用时,remote.<repository>.fetch 值在决定 *什么* 被拉取方面没有任何影响(即,当命令行列出 refspec 时,这些值不用作 refspec);它们仅用于通过充当映射来决定 *哪些* 被拉取的引用被存储在哪里。

remote.<repository>.fetch 值的后一种用法可以通过在命令行上给出 --refmap=<refspec> 参数来覆盖。

PRUNING

Git 的默认处置是保留数据,除非明确丢弃它;这扩展到保留对远程分支的本地引用,即使远程本身已删除这些分支。

如果任其积累,这些过时的引用可能会降低大型繁忙存储库的性能,这些存储库有很多分支更迭,例如,使像 git branch -a --contains <commit> 这样的命令的输出变得不必要地冗长,以及影响任何其他将与已知引用的完整集合一起工作的东西。

这些远程跟踪引用可以使用以下两种方法之一来一次性删除:

# While fetching
$ git fetch --prune <name>

# Only prune, don't fetch
$ git remote prune <name>

要修剪引用作为正常工作流程的一部分,而无需记住运行该命令,请在配置中全局设置 fetch.prune,或每个 remote 设置 remote.<name>.prune。请参阅 git-config[1]

以下是事情变得棘手和更具体的地方。修剪功能实际上并不关心分支,而是将本地 ←→ 远程引用作为 remote 的 refspec 的函数进行修剪(请参阅上面的 <refspec>配置的远程跟踪分支)。

因此,如果 remote 的 refspec 包括例如 refs/tags/*:refs/tags/*,或者您手动运行例如 git fetch --prune <name> "refs/tags/*:refs/tags/*",则不会删除过时的远程跟踪分支,而是删除远程上不存在的任何本地标签。

这可能不是您所期望的,即您想要修剪远程 <name>,但也明确地从中拉取标签,因此当您从中拉取时,您会删除所有本地标签,其中大多数可能一开始就不是来自 <name> 远程的。

因此,当将其与像 refs/tags/*:refs/tags/* 这样的 refspec,或任何其他可能将来自多个 remote 的引用映射到同一本地命名空间的 refspec 一起使用时,请务必小心。

由于保持与远程上的分支和标签同步是一个常见的用例,因此 --prune-tags 选项可以与 --prune 一起提供,以修剪远程上不存在的本地标签,并强制更新那些不同的标签。也可以在配置中使用 fetch.pruneTagsremote.<name>.pruneTags 来启用标签修剪。请参阅 git-config[1]

--prune-tags 选项等效于在 remote 的 refspec 中声明了 refs/tags/*:refs/tags/*。这可能会导致一些看似奇怪的交互

# These both fetch tags
$ git fetch --no-tags origin 'refs/tags/*:refs/tags/*'
$ git fetch --no-tags --prune-tags origin

在没有提供 --prune 或其配置版本的情况下,之所以不会报错,是为了配置版本的灵活性,并保持命令行标志的功能与配置版本的功能之间的 1=1 映射关系。

例如,在 ~/.gitconfig 中配置 fetch.pruneTags=true 是合理的,这样在运行 git fetch --prune 时可以自动删除标签,而不会使每次没有 --prunegit fetch 调用都报错。

当从 URL(而不是指定的远程仓库)获取时,使用 --prune-tags 删除标签也有效。 这些操作都会删除在 origin 上找不到的标签

$ git fetch origin --prune --prune-tags
$ git fetch origin --prune 'refs/tags/*:refs/tags/*'
$ git fetch <url-of-origin> --prune --prune-tags
$ git fetch <url-of-origin> --prune 'refs/tags/*:refs/tags/*'

输出

"git fetch" 的输出取决于使用的传输方法;本节描述了通过 Git 协议(本地或通过 ssh)和 Smart HTTP 协议进行获取时的输出。

获取的状态以表格形式输出,每一行代表一个 ref 的状态。每一行的格式如下:

 <flag> <summary> <from> -> <to> [<reason>]

当使用 --porcelain 时,输出格式旨在可被机器解析。 与人类可读的输出格式相反,它会打印到标准输出而不是标准错误。 每一行的格式如下:

<flag> <old-object-id> <new-object-id> <local-reference>

只有在使用 --verbose 选项时,才会显示最新 ref 的状态。

在紧凑输出模式(通过配置变量 fetch.output 指定)下,如果在另一个字符串中找到完整的 <from><to>,则它将被替换为另一个字符串中的 *。例如,master -> origin/master 变为 master -> origin/*

flag

指示 ref 状态的单个字符

(空格)

表示成功获取的快速前进;

+

表示强制更新成功;

-

表示成功删除的 ref;

t

表示标签更新成功;

*

表示成功获取的新 ref;

!

表示被拒绝或更新失败的 ref;以及

=

表示 ref 是最新的,不需要获取。

summary

对于成功获取的 ref,摘要以适合用作 git log 参数的形式显示 ref 的旧值和新值(在大多数情况下为 <old>..<new>,对于强制的非快进更新,则为 <old>...<new>)。

from

要从中获取的远程 ref 的名称,减去其 refs/<type>/ 前缀。 如果是删除,则远程 ref 的名称为 "(none)"。

to

要更新的本地 ref 的名称,减去其 refs/<type>/ 前缀。

reason

人类可读的解释。 对于成功获取的 ref,不需要解释。 对于失败的 ref,将描述失败的原因。

示例

  • 更新远程跟踪分支

    $ git fetch origin

    除非使用 remote.<repository>.fetch 选项指定非默认的 refspec,否则以上命令会将所有分支从远程 refs/heads/ 命名空间复制到本地 refs/remotes/origin/ 命名空间。

  • 显式使用 refspecs

    $ git fetch origin +seen:seen maint:tmp

    这会通过从远程存储库中的 seenmaint 分支(分别)获取来更新(或根据需要创建)本地存储库中的 seentmp 分支。

    即使 seen 分支没有快进,也会对其进行更新,因为它带有加号前缀; tmp 将不会更新。

  • 查看远程分支,而无需在本地存储库中配置远程仓库

    $ git fetch git://git.kernel.org/pub/scm/git/git.git maint
    $ git log FETCH_HEAD

    第一个命令从 git://git.kernel.org/pub/scm/git/git.git 存储库中获取 maint 分支,第二个命令使用 FETCH_HEAD 通过 git-log[1] 检查该分支。 获取的对象最终将被 git 的内置维护功能删除(请参阅 git-gc[1])。

安全性

fetch 和 push 协议并非旨在防止一方从另一方窃取不打算共享的数据。 如果您有需要保护免受恶意对等方侵害的私有数据,最好的选择是将其存储在另一个存储库中。 这适用于客户端和服务器。 特别是,服务器上的命名空间对于读取访问控制无效; 您应该仅授予对命名空间的读取访问权限,授予您信任其具有对整个存储库的读取访问权限的客户端。

已知的攻击向量如下:

  1. 受害者发送“have”行,以声明其拥有的对象的 ID,这些对象并非明确打算共享,但如果对等方也拥有它们,则可用于优化传输。 攻击者选择要窃取的对象 ID X 并将 ref 发送到 X,但不要求发送 X 的内容,因为受害者已经拥有它。 现在,受害者认为攻击者拥有 X,并且稍后会将 X 的内容发送回攻击者。 (对于客户端来说,通过在客户端有权访问的命名空间中创建对 X 的引用,然后获取它,从而在服务器上执行此攻击最为简单。服务器在客户端上执行此攻击的最可能方法是将 X “合并”到公共分支中,并希望用户在此分支上进行其他工作,并将其推送回服务器而没有注意到合并。)

  2. 与#1中一样,攻击者选择要窃取的对象ID X。受害者发送攻击者已经拥有的对象Y,并且攻击者谎称拥有X而没有Y,因此受害者将Y作为针对X的增量发送。增量向攻击者揭示了X中与Y相似的区域。

配置

本节中此行以下的所有内容均有选择地从 git-config[1] 文档中包含。 内容与在那里找到的内容相同

fetch.recurseSubmodules

此选项控制 git fetch(以及 git pull 中的底层 fetch)是否会递归地获取到已填充的子模块中。 可以将此选项设置为布尔值或 *on-demand*。 如果将其设置为布尔值,则当设置为 true 时,fetch 和 pull 的行为会无条件地递归到子模块中,而当设置为 false 时,则根本不会递归。 当设置为 *on-demand* 时,只有当其超级项目检索到更新子模块引用的提交时,fetch 和 pull 才会递归到已填充的子模块中。 默认为 *on-demand*,如果设置了 submodule.recurse,则默认为该值。

fetch.fsckObjects

如果设置为 true,则 git-fetch-pack 将检查所有获取的对象。 有关检查的内容,请参阅 transfer.fsckObjects。 默认为 false。 如果未设置,则使用 transfer.fsckObjects 的值代替。

fetch.fsck.<msg-id>

行为类似于 fsck.<msg-id>,但由 git-fetch-pack[1] 而不是 git-fsck[1] 使用。 有关详细信息,请参见 fsck.<msg-id> 文档。

fetch.fsck.skipList

行为类似于 fsck.skipList,但由 git-fetch-pack[1] 而不是 git-fsck[1] 使用。 有关详细信息,请参见 fsck.skipList 文档。

fetch.unpackLimit

如果通过 Git 本机传输获取的对象数低于此限制,则这些对象将解包到松散的对象文件中。 但是,如果接收到的对象数等于或超过此限制,则在添加任何缺失的增量基本对象之后,接收到的包将存储为一个包。 从推送存储包可以使推送操作完成得更快,尤其是在较慢的文件系统上。 如果未设置,则使用 transfer.unpackLimit 的值代替。

fetch.prune

如果为 true,则 fetch 将自动表现得好像在命令行上给出了 --prune 选项。 另请参见 remote.<name>.prunegit-fetch[1] 的 PRUNING 部分。

fetch.pruneTags

如果为 true,则在删除时,如果尚未设置,fetch 将自动表现得好像提供了 refs/tags/*:refs/tags/* refspec。 这样可以同时设置此选项和 fetch.prune,以保持与上游 ref 的 1=1 映射。 另请参见 remote.<name>.pruneTagsgit-fetch[1] 的 PRUNING 部分。

fetch.all

如果为 true,则 fetch 将尝试更新所有可用的远程仓库。 可以通过传递 --no-all 或显式指定一个或多个要从中获取的远程仓库来覆盖此行为。 默认为 false。

fetch.output

控制 ref 更新状态的打印方式。 有效值为 fullcompact。 默认值为 full。 有关详细信息,请参见 git-fetch[1] 中的 OUTPUT 部分。

fetch.negotiationAlgorithm

控制在协商要由服务器发送的包文件的内容时,如何发送有关本地存储库中的提交的信息。 设置为“consecutive”以使用一种算法,该算法会遍历连续的提交并检查每个提交。 设置为“skipping”以使用一种算法,该算法跳过提交以努力更快地收敛,但是可能会导致大于需要的包文件; 或设置为“noop”以根本不发送任何信息,这几乎肯定会导致大于需要的包文件,但是会跳过协商步骤。 设置为“default”以覆盖先前所做的设置,并使用默认行为。 默认情况下通常为“consecutive”,但是如果 feature.experimental 为 true,则默认值为“skipping”。 未知值将导致 *git fetch* 报错。

另请参见 git-fetch[1]--negotiate-only--negotiation-tip 选项。

fetch.showForcedUpdates

设置为 false 可以在 git-fetch[1]git-pull[1] 命令中启用 --no-show-forced-updates。 默认为 true。

fetch.parallel

指定一次并行运行的最大获取操作数(子模块,或者当 git-fetch[1]--multiple 选项生效时,是远程仓库)。

值为 0 将给出一些合理的默认值。 如果未设置,则默认为 1。

对于子模块,可以使用 submodule.fetchJobs 配置设置来覆盖此设置。

fetch.writeCommitGraph

设置为 true,以便在每次从远程下载 pack-file 的 git fetch 命令后写入 commit-graph。 使用 --split 选项,大多数执行会在现有 commit-graph 文件之上创建一个非常小的 commit-graph 文件。 有时,这些文件会合并,写入可能需要更长时间。 拥有更新的 commit-graph 文件有助于许多 Git 命令的性能,包括 git merge-basegit push -fgit log --graph。 默认为 false。

fetch.bundleURI

此值存储一个 URI,用于在从原始 Git 服务器执行增量式获取之前,从 bundle URI 下载 Git 对象数据。 这类似于 git-clone[1]--bundle-uri 选项的行为方式。 如果提供的 bundle URI 包含为增量式获取组织的 bundle 列表,则 git clone --bundle-uri 将设置 fetch.bundleURI 值。

如果您修改此值并且您的存储库具有 fetch.bundleCreationToken 值,则在从新的 bundle URI 获取之前删除该 fetch.bundleCreationToken 值。

fetch.bundleCreationToken

当使用 fetch.bundleURI 从使用 "creationToken" 启发式的 bundle 列表进行增量式获取时,此配置值存储已下载的 bundle 的最大 creationToken 值。 如果通告的 creationToken 并非严格大于此值,则此值用于阻止将来下载 bundle。

创建 token 值由提供特定 bundle URI 的提供程序选择。 如果您修改 fetch.bundleURI 处的 URI,请务必在获取之前删除 fetch.bundleCreationToken 值的值。

BUGS

使用 --recurse-submodules 只能获取本地存在的子模块中的新提交,例如在 $GIT_DIR/modules/ 中。 如果上游添加了一个新的子模块,则在克隆该子模块之前(例如通过 git submodule update)无法获取该子模块。 预计这将在未来的 Git 版本中得到修复。

SEE ALSO

GIT

Part of the git[1] suite

scroll-to-top