git-push
更新远程引用及关联对象。
概要
git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed | --signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
[--no-verify] [<repository> [<refspec>...]]描述
从本地仓库更新远程仓库中的一个或多个分支、标签或其他引用,并发送远程上尚不存在的所有必要数据。
最简单的推送方式是 git push <remote> <branch>。git push origin main 将本地 main 分支推送到名为 origin 的远程的 main 分支。
<repository> 参数默认为当前分支的上游,如果没有配置上游则为 origin。
Git 使用以下方式决定推送哪些分支、标签或其他引用(按优先级顺序):
<refspec>参数(例如git push origin main中的main)或--all、--mirror或--tags选项- 正在推送到的仓库的
remote.<name>.push配置 push.default配置。默认为push.default=simple,将推送到与当前分支同名的分支。
如果尚未为当前分支设置上游,git push 可能会失败,具体取决于 push.default 的设置。
您可以通过在那里设置"钩子"来使每次推送到仓库时发生有趣的事情。有关文档,请参阅 git-receive-pack(1)。
选项
<repository>
:推送操作的"远程"目标仓库。此参数可以是 URL(参见下面的 GIT URLS 部分)或远程的名称(参见下面的 REMOTES 部分)。
<refspec>...
:指定要用什么源对象更新什么目标引用。 refspec 的格式为 [+]<src>[:<dst>],例如 main、main:other 或 HEAD^:refs/heads/main。 <src> 通常是本地分支的名称,但它可以是任何任意的 "SHA-1 表达式"(参见 gitrevisions(7))。 <dst> 确定在远程端更新哪个引用。它必须是分支、标签或其他引用的名称,而不是任意表达式。 + 是可选的,与 --force 效果相同。 您可以使用完全展开的形式编写 refspec(例如 refs/heads/main:refs/heads/main),它指定确切的源和目标,或使用较短的形式(例如 main 或 main:other)。以下是 refspec 如何展开的规则以及各种其他特殊 refspec 形式:
- 不带
:<dst>的 <src> 表示更新与 <src> 相同的引用,除非remote.<repository>.push配置指定了不同的 <dst>。 - 如果 <dst> 明确引用远程 <repository> 上的引用,则将其展开为该引用。
- 如果 <src> 解析为以
refs/heads/或refs/tags/开头的引用,则将其前缀添加到 <dst>。 - 特殊 refspec
:(或+:以允许非快速前进更新)指示 Git 推送"匹配的"分支:对于本地存在的每个分支,如果远程端已存在同名分支,则更新远程端。 - <src> 可以包含
*以指示简单的模式匹配。<src>和<dst>中都只能有一个*。 - 以
^开头的 refspec 是负 refspec。这指定要排除的引用。 - 如果 <src> 为空,它从远程仓库删除 <dst> 引用。
tag <tag>展开为refs/tags/<tag>:refs/tags/<tag>。
并非所有更新都允许:有关详细信息,请参阅下面的推送规则。
--all, --branches
推送所有分支(即 refs/heads/ 下的引用);不能与其他 <refspec> 一起使用。
--prune
:移除没有本地对应物的远程分支。例如,如果本地分支不再存在同名的远程分支 tmp 将被移除。这也遵守 refspec。
--mirror
:不是命名每个要推送的引用,而是指定 refs/ 下的所有引用(包括但不限于 refs/heads/、refs/remotes/ 和 refs/tags/)被镜像到远程仓库。新创建的本地引用将被推送到远程端,本地更新的引用将在远程端强制更新,删除的引用将从远程端移除。
-n, --dry-run
执行除实际发送更新之外的所有操作。
--porcelain
:生成机器可读的输出。
-d, --delete
所有列出的引用从远程仓库中删除。这与在所有引用前加冒号相同。
--tags
:推送 refs/tags 下的所有引用,除了命令行上显式列出的 refspec。
--follow-tags
:推送没有此选项时将被推送的所有引用,还推送 refs/tags 中缺失于远程但指向从正在推送的引用可达的提交的带注释标签。
--signed, --no-signed, --signed=(true|false|if-asked)
GPG 签名推送请求以更新接收端的引用,允许钩子检查和/或记录。可能的值为:
false、--no-signed:不尝试签名。true、--signed:如果服务器不支持签名推送,推送将失败。if-asked:当且仅当服务器支持签名推送时签名。如果实际调用gpg --sign失败,推送也会失败。
--atomic, --no-atomic
在远程端使用原子事务(如果可用)。要么所有引用都被更新,要么在出错时不更新任何引用。如果服务器不支持原子推送,推送将失败。
-o <option>, --push-option=<option>
将给定字符串传输到服务器,服务器将其传递给 pre-receive 和 post-receive 钩子。给定字符串不得包含 NUL 或 LF 字符。当给出多个 --push-option=<option> 时,它们都按命令行上列出的顺序发送到另一端。
--receive-pack=<git-receive-pack>, --exec=<git-receive-pack>
远程端 'git-receive-pack' 程序的路径。在通过 ssh 推送到远程仓库且您没有该程序在默认 $PATH 上的目录中时有时很有用。
--force-with-lease, --no-force-with-lease, --force-with-lease=<refname>, --force-with-lease=<refname>:<expect>
通常,git push 拒绝更新不是用于覆盖它的本地引用的祖先的远程引用。 如果远程引用的当前值是期望值,此选项覆盖此限制。否则 git push 失败。 想象一下您必须变基您已经发布的内容。您将不得不绕过"必须快速前进"规则以用变基后的历史替换您最初发布的历史。如果在您变基时其他人在您的原始历史之上构建,远程分支的提示可能会随他们的提交推进,盲目地用 --force 推送将丢失他们的工作。 此选项允许您说明您期望正在更新的历史是您变基并想要替换的。如果远程引用仍指向您指定的提交,您可以确信没有其他人对该引用做任何事情。就像在没有显式锁定的情况下对引用获取"租约"一样,远程引用仅在"租约"仍然有效时更新。 单独的 --force-with-lease 将通过要求所有将被更新的远程引用的当前值与我们为其拥有的远程跟踪分支相同来保护它们。 --force-with-lease=<refname>(不指定期望值)将保护 <refname>(单独),如果它将被更新,通过要求其当前值与我们为其拥有的远程跟踪分支相同。 --force-with-lease=<refname>:<expect> 将保护 <refname>(单独),通过要求其当前值与指定值 <expect> 相同。如果 <expect> 为空字符串,则命名的引用必须尚不存在。 --no-force-with-lease 将取消命令行上所有之前的 --force-with-lease。
-f, --force
通常,git push 拒绝更新不是正在推送的提交的祖先的分支。 此标志禁用该检查、下面推送规则中的其他安全检查以及 --force-with-lease 中的检查。它可能导致远程仓库丢失提交;请谨慎使用。 请注意,--force 应用于所有推送的引用,因此将其与 push.default 设置为 matching 或使用 remote.<name>.push 配置的多个推送目标一起使用可能会覆盖当前分支以外的引用。要强制仅推送到一个分支,请在要推送的 refspec 前使用 +(例如 git push origin +master)。
--force-if-includes, --no-force-if-includes
仅当远程跟踪引用的提示已在本地集成时才强制更新。 此选项启用一个检查,验证远程跟踪引用的提示是否可从基于它进行重写的本地分支的某个"引用日志"条目可达。该检查确保来自远程的任何更新都已在本地合并,如果不是则拒绝强制更新。
--repo=<repository>
:此选项等同于 <repository> 参数。如果两者都指定,命令行参数优先。
-u, --set-upstream
对于每个已更新或成功推送的分支,添加上游(跟踪)引用,供无参数的 git-pull(1) 和其他命令使用。
--thin, --no-thin
这些选项传递给 git-send-pack(1)。当发送方和接收方共享许多相同对象时,薄传输显著减少发送的数据量。默认为 --thin。
-q, --quiet
抑制所有输出,包括更新引用的列表,除非发生错误。进度不报告到标准错误流。
-v, --verbose
详细运行。
--progress
:默认情况下,当标准错误流连接到终端时,进度状态报告到标准错误流,除非指定了 -q。此标志强制即使标准错误流未指向终端也显示进度状态。
--recurse-submodules=(check|on-demand|only|no), --no-recurse-submodules
可用于确保要推送的修订使用的所有子模块提交在远程跟踪分支上可用。
check:Git 将验证在要推送的修订中更改的所有子模块提交在子模块的至少一个远程上可用。如果任何提交缺失,推送将中止并以非零状态退出。on-demand:在要推送的修订中更改的所有子模块将被推送。如果on-demand无法推送所有必要的修订,它也将中止并以非零状态退出。only:所有子模块将被推送,而超级项目保持未推送。no:在不需要子模块递归时覆盖push.recurseSubmodules配置变量。
--verify, --no-verify
切换 pre-push 钩子(参见 githooks(5))。默认为 --verify,给钩子一个阻止推送的机会。使用 --no-verify 时,钩子被完全绕过。
-4, --ipv4
仅使用 IPv4 地址,忽略 IPv6 地址。
-6, --ipv6
仅使用 IPv6 地址,忽略 IPv4 地址。
GIT URLS
通常,URL 包含有关传输协议、远程服务器地址和仓库路径的信息。根据传输协议,其中一些信息可能不存在。
Git 支持 ssh、git、http 和 https 协议(此外,ftp 和 ftps 可用于获取,但这效率低下且已弃用;不要使用它们)。
本机传输(即 git:// URL)不进行认证,在不安全的网络上应谨慎使用。
REMOTES
以下之一的名称可用作 <repository> 参数代替 URL:
- Git 配置文件中的远程:
$GIT_DIR/config $GIT_DIR/remotes目录中的文件$GIT_DIR/branches目录中的文件
上游分支
Git 中的分支可以选择具有上游远程分支。Git 默认使用上游分支进行远程操作。
上游存储在 .git/config 中的 "remote" 和 "merge" 字段中。例如,如果 main 的上游是 origin/main:
[branch "main"]
remote = origin
merge = refs/heads/main输出
"git push" 的输出取决于使用的传输方法;此部分描述通过 Git 协议推送时的输出(本地或通过 ssh)。
推送的状态以表格形式输出,每行代表单个引用的状态。每行格式为:
<flag> <summary> <from> -> <to> (<reason>)如果使用 --porcelain,则输出的每行格式为:
<flag> \t <from>:<to> \t <summary> (<reason>)<flag>
:指示引用状态的单个字符:空格表示成功推送的快速前进;+ 表示成功的强制更新;- 表示成功删除的引用;* 表示成功推送的新引用;! 表示被拒绝或推送失败的引用;= 表示已是最新且不需要推送的引用。
<summary>
:对于成功推送的引用,摘要以适合作为 git log 参数的形式显示引用的新旧值。
from
:正在推送的本地引用的名称,减去其 refs/<type>/ 前缀。
to
:正在更新的远程引用的名称,减去其 refs/<type>/ 前缀。
reason
:人类可读的解释。
推送规则
作为安全功能,git push 命令仅允许某些类型的更新以防止您意外丢失远程上的数据。
因为分支和标签的用途不同,推送到分支的安全规则与推送到标签的规则不同。在以下规则中,"更新"指除删除和创建之外的任何修改。删除和创建始终允许,除非被配置或钩子禁止。
- 如果推送目标是分支(
refs/heads/*):仅允许快速前进更新,即目标必须是源提交的祖先。源必须是提交。 - 如果推送目标是标签(
refs/tags/*):所有更新将被拒绝。源可以是任何对象。 - 如果推送目标不是分支或标签:
- 如果源是树或 blob 对象,任何更新将被拒绝
- 如果源是标签或提交对象,允许任何快速前进更新
您可以通过传递 --force 或在 refspec 前添加可选的 + 来覆盖这些规则。唯一的例外是,没有足够的强制力会使分支接受非提交对象,强制也不会使远程仓库接受它配置为拒绝的推送。
钩子和配置也可以覆盖或修改这些规则,参见 git-config(1) 中的 receive.denyNonFastForwards 和 receive.denyDeletes 以及 githooks(5) 中的 pre-receive 和 update。
关于快速前进的说明
当更新将分支(或更一般地说,引用)从指向提交 A 改为指向另一个提交 B 时,当且仅当 B 是 A 的后代时,才称为快速前进更新。
在从 A 到 B 的快速前进更新中,原始提交 A 构建在其上的提交集是新提交 B 构建在其上的提交集的子集。因此,它不会丢失任何历史。
相反,非快速前进更新将丢失历史。例如,假设您和其他人从同一个提交 X 开始,您构建了通向提交 B 的历史,而其他人构建了通向提交 A 的历史。
示例
git push
:等同于 git push <remote>,其中 <remote> 是当前分支的远程(或 origin,如果当前分支未配置远程)。
git push origin
:在没有额外配置的情况下,如果当前分支与上游同名,则将当前分支推送到配置的上游,否则报错而不推送。
git push origin :
:推送"匹配的"分支到 origin。
git push origin master
:在源仓库中找到匹配 master 的引用,并用它更新 origin 仓库中的相同引用。如果 master 在远程不存在,它将被创建。
git push origin HEAD
:将当前分支推送到远程同名分支的便捷方式。
git push origin HEAD:master
:将当前分支推送到 origin 仓库中匹配 master 的远程引用。
git push origin :experimental
:在 origin 仓库中找到匹配 experimental 的引用并删除它。
配置
以下内容选自 git-config(1) 文档:
push.default
:定义在未给出 refspec 时 git push 应采取的操作。不同的值适合特定的工作流。可能的值为:
nothing:除非给出 refspec,否则不推送任何内容(报错)。这主要面向想要通过始终显式来避免错误的人。current:推送当前分支以更新接收端同名的分支。在中心和非中心工作流中都有效。upstream:将当前分支推回到其更改通常集成到当前分支的分支(称为@{upstream})。此模式仅在您推送到通常从中拉取的同一仓库(即中心工作流)时有意义。tracking:这是upstream的已弃用同义词。simple:推送当前分支到远程同名分支。如果您使用中心化工作流(推送到您从中拉取的同一仓库,通常是origin),则需要配置同名的上游分支。此模式是 Git 2.0 以来的默认值,是适合初学者的最安全选项。matching:推送两端同名的所有分支。这曾经是默认值,但自 Git 2.0 起不再是(simple是新默认值)。
push.followTags
:如果设置为 true,默认启用 --follow-tags 选项。
push.gpgSign
:可设置为布尔值或字符串 if-asked。true 值导致所有推送都被 GPG 签名。
push.pushOption
:当命令行上未给出 --push-option=<option> 参数时,git push 表现为如同此变量的每个 <option> 都作为 --push-option=<option> 给出。
push.recurseSubmodules
:可以是 check、on-demand、only 或 no,行为与 push --recurse-submodules 相同。
push.useForceIfIncludes
:如果设置为 true,等同于在命令行上指定 --force-if-includes 作为 git-push(1) 的选项。
push.negotiate
:如果设置为 true,尝试通过客户端和服务器尝试查找公共提交的协商轮次来减少发送的包文件大小。
push.useBitmaps
:如果设置为 false,即使 pack.useBitmaps 为 true,也禁用 git push 使用位图,而不阻止其他 git 操作使用位图。默认为 true。
安全
获取和推送协议不是为了防止一方从另一个仓库窃取不打算共享的数据而设计的。如果您有需要保护免受恶意对等方侵害的私有数据,最好的选择是将其存储在另一个仓库中。
Git
git(1) 套件的一部分
