Git
英语 ▾ 主题 ▾ 最新版本 ▾ git-pull 最后更新于 2.46.2

名称

git-pull - 从另一个仓库或本地分支获取并整合

概要

git pull [<options>] [<repository> [<refspec>…​]]

描述

将远程仓库的更改整合到当前分支。如果当前分支落后于远程分支,默认情况下它将快速向前移动当前分支以匹配远程分支。如果当前分支和远程分支有分歧,用户需要指定如何使用 --rebase--no-rebase(或 pull.rebase 中的相应配置选项)来协调分歧的分支。

更准确地说,git pull 会运行带有指定参数的 git fetch,然后根据配置选项或命令行标志,调用 git rebasegit merge 来协调分歧的分支。

<repository> 应该与传递给 git-fetch[1] 的远程仓库的名称相同。<refspec> 可以命名一个任意的远程引用(例如,标签的名称)甚至是一组具有对应远程跟踪分支的引用(例如,refs/heads/*:refs/remotes/origin/*),但通常它是远程仓库中分支的名称。

<repository> 和 <branch> 的默认值从当前分支的“remote”和“merge”配置中读取,由 git-branch[1] --track 设置。

假设存在以下历史记录,当前分支为“master

	  A---B---C master on origin
	 /
    D---E---F---G master
	^
	origin/master in your repository

然后“git pull”将从远程 master 分支获取并重放自它与本地 master(即 E)分歧以来的更改,直到它当前的提交(C)在 master 上,并将结果记录在一个新的提交中,以及两个父提交的名称和用户描述更改的日志消息。

	  A---B---C origin/master
	 /         \
    D---E---F---G---H master

有关详细信息,包括如何呈现和处理冲突,请参阅 git-merge[1]

在 Git 1.7.0 或更高版本中,要取消有冲突的合并,请使用 git reset --merge警告:在较旧版本的 Git 中,不建议在未提交更改的情况下运行 git pull:虽然可以实现,但在发生冲突的情况下会让你处于难以退出的状态。

如果任何远程更改与本地未提交的更改重叠,合并将自动取消,并且工作树保持不变。通常,在拉取之前最好将本地更改整理好,或使用 git-stash[1] 将它们存起来。

选项

-q
--quiet

这会传递给底层的 git-fetch 以抑制传输过程中的报告,以及底层的 git-merge 以抑制合并过程中的输出。

-v
--verbose

将 --verbose 传递给 git-fetch 和 git-merge。

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

此选项控制是否应该获取填充子模块的新提交,以及是否也应该更新活动子模块的工作树(参见 git-fetch[1]git-config[1]gitmodules[5])。

如果检出是通过 rebase 完成的,本地子模块提交也会被 rebase。

如果更新是通过合并完成的,子模块冲突将被解决并检出。

--commit
--no-commit

执行合并并提交结果。此选项可用于覆盖 --no-commit。仅在合并时有用。

使用 --no-commit 执行合并,并在创建合并提交之前停止,以便用户有机会在提交之前检查和进一步调整合并结果。

请注意,快速向前更新不会创建合并提交,因此无法使用 --no-commit 停止这些合并。因此,如果你想确保你的分支不会被合并命令更改或更新,请使用 --no-ff 和 --no-commit。

--edit
-e
--no-edit

在提交成功的机械合并之前调用编辑器以进一步编辑自动生成的合并消息,以便用户可以解释和证明合并。--no-edit 选项可用于接受自动生成的邮件(一般不建议这样做)。

较旧的脚本可能依赖于不允许用户编辑合并日志消息的历史行为。当它们运行 git merge 时,会看到一个打开的编辑器。为了使此类脚本更容易适应更新的行为,可以在它们的开头将环境变量 GIT_MERGE_AUTOEDIT 设置为 no

--cleanup=<mode>

此选项确定在提交之前如何清理合并消息。有关更多详细信息,请参阅 git-commit[1]。此外,如果 <mode> 的值为 scissors,则在合并冲突的情况下,在将 MERGE_MSG 传递给提交机制之前,会将剪刀附加到 MERGE_MSG

--ff-only

只有在没有分歧的本地历史记录的情况下才更新到新的历史记录。这是没有提供协调分歧历史记录的方法(通过 --rebase=* 标志)时的默认值。

--ff
--no-ff

在合并而不是 rebase 时,指定在合并的历史记录已经是当前历史记录的后代时如何处理合并。如果请求合并,--ff 是默认值,除非合并一个未存储在其在 refs/tags/ 层次结构中的自然位置的带注释的(可能签名的)标签,在这种情况下,将假定 --no-ff

使用 --ff,如果可能,将合并解决为快速向前(仅更新分支指针以匹配合并的分支;不要创建合并提交)。如果不可能(当合并的历史记录不是当前历史记录的后代时),创建合并提交。

使用 --no-ff,在所有情况下创建合并提交,即使合并可以被解决为快速向前。

-S[<keyid>]
--gpg-sign[=<keyid>]
--no-gpg-sign

对生成的合并提交进行 GPG 签名。keyid 参数是可选的,默认为提交者身份;如果指定,它必须直接附加到选项,不能有空格。--no-gpg-sign 用于抵消 commit.gpgSign 配置变量和更早的 --gpg-sign

--log[=<n>]
--no-log

除了分支名称外,还应使用最多 <n> 个实际合并提交的一行描述填充日志消息。另请参阅 git-fmt-merge-msg[1]。仅在合并时有用。

使用 --no-log 不列出从实际合并提交中的一行描述。

--signoff
--no-signoff

在提交日志消息末尾添加由提交者添加的 Signed-off-by 尾部。签署的意义取决于您提交的项目。例如,它可能证明提交者有权在项目的许可下提交工作,或者同意某些贡献者代表,例如开发者起源证书。(有关 Linux 内核和 Git 项目使用的证书,请参阅 https://developercertificate.org。) 请咨询您要贡献的项目的文档或领导,以了解签署在该项目中的使用方式。

--no-signoff 选项可用于撤销命令行上早先的 --signoff 选项。

--stat
-n
--no-stat

在合并结束时显示一个 diffstat。diffstat 也由配置选项 merge.stat 控制。

使用 -n 或 --no-stat 在合并结束时不显示 diffstat。

--squash
--no-squash

生成工作树和索引状态,就像实际合并发生一样(除了合并信息),但实际上不会进行提交,移动 HEAD 或记录 $GIT_DIR/MERGE_HEAD(以使下一个 git commit 命令创建合并提交)。这使您可以在当前分支之上创建单个提交,其效果与合并另一个分支相同(如果是章鱼合并,则效果与合并多个分支相同)。

使用 --no-squash 执行合并并提交结果。此选项可用于覆盖 --squash。

使用 --squash 时,不允许使用 --commit,并将失败。

仅在合并时有用。

--[no-]verify

默认情况下,会运行 pre-merge 和 commit-msg 钩子。如果指定了 --no-verify,则会绕过这些钩子。另请参阅 githooks[5]。仅在合并时有用。

-s <strategy>
--strategy=<strategy>

使用给定的合并策略;可以多次提供该选项,以指定尝试的顺序。如果没有 -s 选项,则使用内置策略列表(在合并单个头时使用 ort,否则使用 octopus)。

-X <option>
--strategy-option=<option>

将合并策略特定的选项传递到合并策略。

--verify-signatures
--no-verify-signatures

验证要合并的侧分支的顶端提交是否已使用有效密钥签名,即具有有效 uid 的密钥:在默认信任模型中,这意味着签名密钥已由受信任的密钥签名。如果侧分支的顶端提交未使用有效密钥签名,则合并将中止。

仅在合并时有用。

--summary
--no-summary

与 --stat 和 --no-stat 的同义词;这些选项已弃用,将在未来版本中删除。

--autostash
--no-autostash

在操作开始之前自动创建临时存储条目,将其记录在 ref MERGE_AUTOSTASH 中,并在操作结束之后应用它。这意味着您可以在脏工作树上运行该操作。但是,请谨慎使用:在成功合并之后,最终的存储应用可能会导致非平凡的冲突。

--allow-unrelated-histories

默认情况下,git merge 命令拒绝合并没有共同祖先的历史记录。此选项可用于在合并两个独立开始其生命周期的项目的历史记录时覆盖此安全措施。由于这是一种非常罕见的情况,因此不存在默认情况下启用此选项的配置变量,并且将不会添加。

仅在合并时有用。

-r
--rebase[=(false|true|merges|interactive)]

如果为 true,则在提取之后将当前分支重新定位到上游分支之上。如果存在与上游分支相对应的远程跟踪分支,并且上游分支自上次提取以来已重新定位,则重新定位将使用该信息来避免重新定位非本地更改。

如果设置为 merges,则使用 git rebase --rebase-merges 重新定位,以便将本地合并提交包含在重新定位中(有关详细信息,请参阅 git-rebase[1])。

如果为 false,则将上游分支合并到当前分支。

如果为 interactive,则启用重新定位的交互模式。

如果您希望 git pull 始终使用 --rebase 而不是合并,请参阅 git-config[1] 中的 pull.rebasebranch.<name>.rebasebranch.autoSetupRebase

注意
这是一种可能危险的操作模式。它会重写历史记录,如果您已经发布了该历史记录,则效果不佳。除非您仔细阅读了 git-rebase[1],否则不要使用此选项。
--no-rebase

这是 --rebase=false 的简写。

--[no-]all

提取所有远程仓库,但设置了 remote.<name>.skipFetchAll 配置变量的远程仓库除外。这会覆盖配置变量 fetch.all`。

-a
--append

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

--atomic

使用原子事务来更新本地 ref。所有 ref 都会被更新,或者在发生错误时,不会更新任何 ref。

--depth=<depth>

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

--deepen=<depth>

与 --depth 相似,但它指定的是从当前浅层边界到每个远程分支历史记录顶端的提交数量。

--shallow-since=<date>

加深或缩短浅层存储库的历史记录,以包含 <date> 之后的所有可到达提交。

--shallow-exclude=<revision>

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

--unshallow

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

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

--update-shallow

默认情况下,当从浅层存储库提取时,git fetch 会拒绝需要更新 .git/shallow 的 ref。此选项会更新 .git/shallow,并接受这些 ref。

--negotiation-tip=<commit|glob>

默认情况下,Git 会向服务器报告所有本地 ref 可到达的提交,以查找共同提交,从而尝试减少要接收的 packfile 的大小。如果指定了此选项,Git 将仅报告从给定顶端可到达的提交。这对于在用户知道哪个本地 ref 很有可能与要提取的上游 ref 共享提交时加速提取非常有用。

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

此选项的参数可以是 ref 名称上的 glob、ref 或提交的(可能缩写的)SHA-1。指定 glob 等同于多次指定此选项,每次都针对每个匹配的 ref 名称。

另请参阅 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 配置选项。

-f
--force

git fetch<src>:<dst> refspec 一起使用时,它可能会拒绝更新本地分支,如 git-fetch[1] 文档的 <refspec> 部分所述。此选项会覆盖该检查。

-k
--keep

保留下载的 pack。

--prefetch

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

-p
--prune

在提取之前,删除远程仓库中不再存在的任何远程跟踪引用。如果仅由于默认标签自动跟踪或 --tags 选项,则标签不会被修剪。但是,如果由于显式 refspec(在命令行或远程配置中,例如如果远程仓库是使用 --mirror 选项克隆的)而提取了标签,则它们也会被修剪。提供 --prune-tags 等同于提供标签 refspec。

--no-tags

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

--refmap=<refspec>

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

-t
--tags

除了其他将要提取的内容之外,还从远程仓库提取所有标签 (即,将远程标签 `refs/tags/*` 提取到同名的本地标签中)。仅使用此选项不会将标签进行修剪,即使使用了 `--prune` (如果标签也是显式引用规格的目标,则标签可能会被修剪;参见 `--prune`)。

-j
--jobs=<n>

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

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

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

--set-upstream

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

--upload-pack <upload-pack>

如果给出,并且要提取的仓库由 git fetch-pack 处理,则将 `--exec=<upload-pack>` 传递给该命令,以指定在另一端运行的命令的非默认路径。

--progress

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

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

在使用协议版本 2 通信时,将给定的字符串传输到服务器。给定的字符串不能包含 NUL 或 LF 字符。服务器对服务器选项的处理,包括未知选项,是特定于服务器的。当给出多个 `--server-option=<option>` 时,它们都将按照命令行中列出的顺序发送到另一端。

--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 部分)。

<refspec>

指定要提取的引用以及要更新的本地引用。当命令行上没有出现任何 <refspec> 时,要提取的引用将从 `remote.<repository>.fetch` 变量中读取 (参见 git-fetch[1] 中的“配置的远程跟踪分支”部分)。

<refspec> 参数的格式是可选的加号 `+`,后跟源 <src>,后跟冒号 `:`,后跟目标引用 <dst>。当 <dst> 为空时,可以省略冒号。<src> 通常是一个引用,但它也可以是一个完整的十六进制对象名称。

<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] 推送时一样,上述关于哪些更新不允许的所有规则都可以通过在引用规格中添加一个可选的引导 `+` 来覆盖 (或使用 `--force` 命令行选项)。唯一的例外是,任何强制操作都不能使 `refs/heads/*` 命名空间接受非提交对象。

注意
当您要提取的远程分支已知会被定期回退和重新调整基线时,预计它的新顶端不会是它先前顶端的子代 (如上次提取时存储在您的远程跟踪分支中)。您将希望使用 `+` 符号来指示此类分支需要非快速转发更新。无法确定或声明分支将在具有此行为的仓库中提供;拉取用户只需知道这是该分支的预期使用模式。
注意
git pull 命令行上直接列出多个 <refspec> 与在您的配置中为 <repository> 设置多个 `remote.<repository>.fetch` 条目,并运行没有显式 <refspec> 参数的 git pull 命令之间存在差异。在命令行上显式列出的 <refspec> 将始终在提取后合并到当前分支中。换句话说,如果您列出多个远程引用,git pull 将创建一个章鱼合并。另一方面,如果您没有在命令行上列出任何显式 <refspec> 参数,git pull 将提取在 `remote.<repository>.fetch` 配置中找到的所有 <refspec>,并将第一个找到的 <refspec> 合并到当前分支中。这是因为很少从远程引用创建章鱼,而通过提取多个引用来一次性跟踪多个远程头部通常很有用。

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 链接。

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 也原生支持以下语法

这两种语法基本等价,除非在克隆时,前者暗示 --local 选项。更多详情见 git-clone[1]

git clone, git 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。

远程仓库

以下的名称可以作为 <repository> 参数,代替 URL

  • Git 配置文件中的远程仓库:$GIT_DIR/config

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

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

所有这些都允许你省略命令行中的 refspec,因为它们每个都包含一个 refspec,Git 会默认使用它。

配置文件中的命名远程仓库

可以选择提供之前使用 git-remote[1]git-config[1] 或者手动编辑 $GIT_DIR/config 文件配置过的远程仓库名称。此远程仓库的 URL 会被用来访问仓库。此远程仓库的 refspec 会在你没有在命令行提供 refspec 时被用作默认值。配置文件中的条目会像这样出现

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

<pushurl> 仅用于推送。它是可选的,默认值为 <URL>。推送至远程仓库会影响所有定义的 pushurl,或者如果未定义 pushurl,则会影响所有定义的 url。但是,如果定义了多个 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> 是可选的。

根据操作,Git 会使用以下 refspec 中的一个,如果你没有在命令行提供的话。<branch>$GIT_DIR/branches 中此文件的名称,<head> 默认值为 master

git fetch 使用

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

git push 使用

	HEAD:refs/heads/<head>

合并策略

合并机制(git mergegit pull 命令)允许使用 -s 选项选择后端 合并策略。一些策略还可以使用自己的选项,这些选项可以通过向 git merge 和/或 git pull 提供 -X<option> 参数来传递。

ort

这是在拉取或合并一个分支时默认的合并策略。此策略只能使用 3 路合并算法解决两个头。当存在多个可以用于 3 路合并的共同祖先时,它会创建共同祖先的合并树,并将其用作 3 路合并的参考树。据报道,这会导致更少的合并冲突,而不会因对从 Linux 2.6 内核开发历史中获取的实际合并提交进行的测试而导致错误合并。此外,此策略可以检测和处理涉及重命名的合并。它不使用检测到的复制。此算法的名称是首字母缩略词 ("Ostensibly Recursive's Twin"),它来自于这样一个事实:它是作为对先前默认算法 recursive 的替代而编写的。

ort 策略可以使用以下选项

ours

此选项强制将冲突的块自动解决干净,优先考虑 我们的 版本。来自另一棵树的变化,只要不与我们的部分冲突,就会反映在合并结果中。对于二进制文件,整个内容将从我们的部分获取。

不要将此与 ours 合并策略混淆,后者根本不会查看另一棵树包含的内容。它会丢弃另一棵树所做的所有事情,声明 我们的 历史包含其中发生的事件。

theirs

这是 ours 的反面;请注意,与 ours 不同,没有 theirs 合并策略与之混淆。

ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol

为了进行三路合并,将具有指定类型空白变化的行视为未改变。与其他变化混合的空白变化不会被忽略。另见 git-diff[1] -b-w--ignore-space-at-eol--ignore-cr-at-eol

  • 如果 他们的 版本只是对一行引入了空白变化,则使用 我们的 版本;

  • 如果 我们的 版本引入了空白变化,但 他们的 版本包含实质性变化,则使用 他们的 版本;

  • 否则,合并将按通常方式进行。

renormalize

这会在解决三路合并时运行文件的三个阶段的虚拟检出和检入。此选项旨在用于合并具有不同清理过滤器或行尾规范化规则的分支。更多详情见 gitattributes[5] 中的 "合并具有不同检出/检入属性的分支"。

no-renormalize

禁用 renormalize 选项。这会覆盖 merge.renormalize 配置变量。

find-renames[=<n>]

开启重命名检测,可选地设置相似度阈值。这是默认值。这会覆盖 merge.renames 配置变量。另见 git-diff[1] --find-renames

rename-threshold=<n>

find-renames=<n> 的过时同义词。

subtree[=<path>]

此选项是 subtree 策略的更高级形式,其中策略会在合并时猜测两棵树必须如何移动以相互匹配。相反,指定路径会被加前缀(或从开头剥离),以使两棵树的形状匹配。

recursive

这只能使用 3 路合并算法解决两个头。当存在多个可以用于 3 路合并的共同祖先时,它会创建共同祖先的合并树,并将其用作 3 路合并的参考树。据报道,这会导致更少的合并冲突,而不会因对从 Linux 2.6 内核开发历史中获取的实际合并提交进行的测试而导致错误合并。此外,这可以检测和处理涉及重命名的合并。它不使用检测到的复制。这是 Git v0.99.9k 到 v2.33.0 之间用于解决两个头的默认策略。

recursive 策略使用与 ort 相同的选项。但是,还有三个 ort 忽略的额外选项(上面没有记录),这些选项可能对 recursive 策略有用

patience

diff-algorithm=patience 的过时同义词。

diff-algorithm=[patience|minimal|histogram|myers]

在合并时使用不同的 diff 算法,这可以帮助避免由于不重要的匹配行(例如来自不同函数的大括号)而发生的错误合并。另见 git-diff[1] --diff-algorithm。请注意,ort 特别使用 diff-algorithm=histogram,而 recursive 默认使用 diff.algorithm 配置设置。

no-renames

关闭重命名检测。这会覆盖 merge.renames 配置变量。另见 git-diff[1] --no-renames

resolve

这只能使用 3 路合并算法解决两个头(即当前分支和另一个你从中拉取的分支)。它尝试仔细检测交叉合并歧义。它不处理重命名。

octopus

这会解决多个头的情况,但拒绝进行需要手动解决的复杂合并。它主要用于将主题分支头捆绑在一起。这是在拉取或合并多个分支时默认的合并策略。

ours

这会解决任意数量的头,但合并后的树始终是当前分支头的树,实际上忽略了所有其他分支的所有变化。它用于取代侧分支的旧开发历史。请注意,这不同于 recursive 合并策略的 -Xours 选项。

subtree

这是一个修改后的ort策略。在合并树 A 和 B 时,如果 B 对应于 A 的一个子树,则首先调整 B 以匹配 A 的树结构,而不是在同一级别读取树。这种调整也应用于共同祖先树。

对于使用 3 路合并的策略(包括默认策略ort),如果在两个分支上都进行了更改,但后来在一个分支上恢复了更改,则该更改将出现在合并结果中;有些人觉得这种行为令人困惑。这是因为在执行合并时只考虑了头部和合并基础,而不是单个提交。因此,合并算法将恢复的更改视为没有更改,并用更改后的版本替换。

默认行为

人们经常在不给出任何参数的情况下使用git pull。传统上,这相当于说git pull origin。但是,当在分支<name>上存在配置branch.<name>.remote时,该值将代替origin使用。

为了确定要从中获取的 URL,将查询配置remote.<origin>.url的值,如果没有这样的变量,则使用$GIT_DIR/remotes/<origin>中的URL:行上的值。

为了确定在命令行上没有使用任何 refspec 参数的情况下运行命令时要获取(并可选地存储在远程跟踪分支中)哪些远程分支,将查询配置变量remote.<origin>.fetch的值,如果没有,则查询$GIT_DIR/remotes/<origin>并使用它的Pull:行。除了 OPTIONS 部分中描述的 refspec 格式之外,还可以使用类似于以下形式的通配符 refspec

refs/heads/*:refs/remotes/origin/*

通配符 refspec 必须具有非空的 RHS(即必须存储在远程跟踪分支中获取的内容),并且其 LHS 和 RHS 必须以/*结尾。以上指定所有远程分支都使用refs/remotes/origin/层次结构下的远程跟踪分支进行跟踪,名称相同。

确定获取后要合并哪个远程分支的规则比较复杂,为了不破坏向后兼容性。

如果在git pull的命令行上给出了明确的 refspec,则所有 refspec 都将被合并。

当命令行上没有给出 refspec 时,git pull将使用来自配置或$GIT_DIR/remotes/<origin>的 refspec。在这种情况下,以下规则适用

  1. 如果当前分支<name>存在branch.<name>.merge配置,则它是远程站点上合并的分支的名称。

  2. 如果 refspec 是通配符,则不会合并任何内容。

  3. 否则,将合并第一个 refspec 的远程分支。

示例

  • 更新您从其克隆的存储库的远程跟踪分支,然后将其中一个分支合并到您当前的分支中

    $ git pull
    $ git pull origin

    通常合并的分支是远程存储库的 HEAD,但选择由 branch.<name>.remote 和 branch.<name>.merge 选项决定;有关详细信息,请参见git-config[1]

  • 将远程分支next合并到当前分支中

    $ git pull origin next

    这会在 FETCH_HEAD 中暂时保留next的副本,并更新远程跟踪分支origin/next。可以通过调用 fetch 和 merge 来执行相同操作

    $ git fetch origin
    $ git merge origin/next

如果您尝试了一个导致复杂冲突的 pull 并想重新开始,可以使用git reset恢复。

安全

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

已知的攻击媒介如下

  1. 受害者发送 "have" 行,宣传它拥有的对象的 ID,这些对象并非明确旨在共享,但如果对等体也拥有它们,则可以用来优化传输。攻击者选择一个要窃取的对象 ID X 并发送指向 X 的 ref,但不需要发送 X 的内容,因为受害者已经拥有它。现在,受害者相信攻击者拥有 X,并在稍后将 X 的内容发送回攻击者。(对于客户端在服务器上执行此攻击最直接,通过在客户端有权访问的命名空间中创建指向 X 的 ref,然后获取它。服务器对客户端执行此攻击最可能的方式是将 X "合并" 到公共分支,并希望用户在此分支上执行更多工作并将它推回服务器,而不会注意到合并。)

  2. 如 #1 中所示,攻击者选择一个要窃取的对象 ID X。受害者发送一个攻击者已经拥有的对象 Y,攻击者错误地声称拥有 X 而不拥有 Y,因此受害者将 Y 作为 X 的增量发送。增量向攻击者揭示了 X 中与 Y 相似的区域。

错误

目前,使用 --recurse-submodules 只能获取已检出子模块中的新提交。例如,当上游在刚获取的超项目提交中添加了一个新的子模块时,无法获取子模块本身,因此在没有再次获取的情况下,无法检出该子模块。预计将在未来的 Git 版本中修复此问题。

GIT

git[1] 套件的一部分

scroll-to-top