git-p4
从 Perforce 仓库导入和提交。
概要
'git p4 clone' [<sync-options>] [<clone-options>] <p4-depot-path>...
'git p4 sync' [<sync-options>] [<p4-depot-path>...]
'git p4 rebase'
'git p4 submit' [<submit-options>] [<master-branch-name>]描述
此命令提供了一种使用 Git 与 p4 仓库交互的方式。
使用 'git p4 clone' 从现有 p4 仓库创建新的 Git 仓库,给它一个或多个 p4 仓库路径。使用 'git p4 sync' 从 p4 更改中合并新的提交。'sync' 命令也用于包含来自其他 p4 仓库路径的新分支。使用 'git p4 submit' 将 Git 更改提交回 p4。'git p4 rebase' 命令执行同步加上将当前分支变基到更新的 p4 远程分支上。
示例
克隆仓库:
$ git p4 clone //depot/path/project在新创建的 Git 仓库中做一些工作:
$ cd project $ vi foo.h $ git commit -a -m "edited foo.h"使用 p4 的最新更改更新 Git 仓库,将您的工作变基到上面:
$ git p4 rebase将您的提交提交回 p4:
$ git p4 submit
命令
Clone
通常,'git p4 clone' 用于从现有 p4 仓库创建新的 Git 目录:
$ git p4 clone //depot/path/project这会:
- 在名为 'project' 的子目录中创建一个空的 Git 仓库。
- 将给定 p4 仓库路径的 head 修订的全部内容导入到 Git 分支 'refs/remotes/p4/master' 中的单个提交。
- 创建本地分支 'master',从此远程分支检出。
要在 Git 中重现整个 p4 历史,在仓库路径上使用 '@all' 修饰符:
$ git p4 clone //depot/path/project@allSync
随着 p4 仓库中的开发继续,可以使用以下方式将这些更改包含在 Git 仓库中:
$ git p4 sync此命令在 p4 中查找新更改并将它们作为 Git 提交导入。
P4 仓库也可以使用 'git p4 sync' 添加到现有 Git 仓库中:
$ mkdir repo-git
$ cd repo-git
$ git init
$ git p4 sync //path/in/your/perforce/depot这将指定的仓库导入到现有 Git 仓库中的 'refs/remotes/p4/master'。--branch 选项可用于指定用于 p4 内容的不同分支。
如果 Git 仓库包含分支 'refs/remotes/origin/p4',这些将在 'git p4 sync' 期间首先被获取和查询。由于直接从 p4 导入比从 Git 远程拉取更改慢得多,这在多开发者环境中很有用。
如果有多个分支,执行 'git p4 sync' 将自动使用"分支检测"算法尝试将新更改划分为正确的分支。可以使用 --branch 选项覆盖此行为以仅指定要更新的单个分支。
Rebase
常见的工作模式是从 p4 仓库获取最新更改并将它们与本地未提交的更改合并。通常,p4 仓库是所有代码的最终位置,因此变基工作流是有意义的此命令执行 'git p4 sync' 后跟 'git rebase' 将本地提交移动到更新的 p4 更改之上。
$ git p4 rebaseSubmit
将更改从 Git 仓库提交回 p4 仓库需要单独的 p4 客户端工作区。应使用 P4CLIENT 环境变量或 Git 配置变量 'git-p4.client' 指定。p4 客户端必须存在,但如果客户端根目录不存在,则会创建并填充。
要提交当前 Git 分支中但不在 'p4/master' 分支中的所有更改,使用:
$ git p4 submit要指定当前分支以外的分支,使用:
$ git p4 submit topicbranch要指定单个提交或一系列提交,使用:
$ git p4 submit --commit <sha1>
$ git p4 submit --commit <sha1..sha1>上游引用通常是 'refs/remotes/p4/master',但可以使用 --origin= 命令行选项覆盖。
p4 更改将作为调用 'git p4 submit' 的用户创建。--preserve-user 选项将导致所有权根据 Git 提交的作者进行修改。此选项需要 p4 中的管理员权限,可以使用 'p4 protect' 授予。
要搁置更改而不是提交,使用 --shelve 和 --update-shelve:
$ git p4 submit --shelve
$ git p4 submit --update-shelve 1234 --update-shelve 2345Unshelve
取消搁置将获取搁置的 P4 更改列表,并在分支 refs/remotes/p4-unshelved/<changelist> 中生成等效的 git 提交。
git 提交是相对于当前 origin 修订(默认为 HEAD)创建的。基于 origin 创建父提交,然后基于该父提交创建取消搁置提交。
origin 修订可以通过 "--origin" 选项更改。
如果 refs/remotes/p4-unshelved 中的目标分支已存在,旧的将被重命名。
$ git p4 sync
$ git p4 unshelve 12345
$ git show p4-unshelved/12345
<通过 p4 向相同文件提交更多更改>
$ git p4 unshelve 12345
<拒绝取消搁置,直到 git 与 p4 再次同步>选项
通用选项
除 clone 外的所有命令都接受这些选项。
--git-dir <dir>
:设置 GIT_DIR 环境变量。参见 git(1)。
-v, --verbose
提供更多信息。
Sync 选项
这些选项可在初始 'clone' 以及后续的 'sync' 操作中使用。
--branch <ref>
:将更改导入 <ref> 而不是 refs/remotes/p4/master。如果 <ref> 以 refs/ 开头,则按原样使用。否则,如果它不以 p4/ 开头,则添加该前缀。 默认情况下,不以 refs/ 开头的 <ref> 被视为远程跟踪分支的名称(在 refs/remotes/ 下)。可以使用 --import-local 选项修改此行为。 默认 <ref> 为 "master"。 此示例将新的远程 "p4/proj2" 导入现有的 Git 仓库:
$ git init
$ git p4 sync --branch=refs/remotes/p4/proj2 //depot/proj2--detect-branches
:使用分支检测算法在 p4 中查找新路径。在下面的"分支检测"中有文档记录。
--changesfile <file>
:仅导入 'file' 中列出的 p4 更改号,每行一个。通常,'git p4' 检查当前 p4 仓库状态并检测应导入的更改。
--silent
:不打印任何进度信息。
--detect-labels
:查询与仓库路径关联的 p4 标签,并将它们作为 Git 中的标签添加。用途有限,因为仅导入与新更改列表关联的标签。已弃用。
--import-labels
:从 p4 将标签导入 Git。
--import-local
:默认情况下,p4 分支存储在 'refs/remotes/p4/' 中,在那里它们将被 git-branch(1) 和其他命令视为远程跟踪分支。此选项改为将 p4 分支放在 'refs/heads/p4/' 中。请注意,未来的同步操作也必须指定 --import-local,以便它们可以在 refs/heads 中找到 p4 分支。
--max-changes <n>
:最多导入 'n' 个更改,而不是给定修订说明符中包含的整个更改范围。典型用法是使用 '@all' 作为修订说明符,但然后使用 '--max-changes 1000' 仅导入最后 1000 个修订而不是整个修订历史。
--changes-block-size <n>
:将 '@all' 等修订说明符转换为特定更改号列表时使用的内部块大小。不是使用单次调用 'p4 changes' 来查找转换的完整更改列表,而是有一系列对 'p4 changes -m' 的调用,每个调用请求给定大小的一个更改块。默认块大小为 500,通常应该合适。
--keep-path
:文件名从 p4 仓库路径到 Git 的映射默认涉及移除整个仓库路径。使用此选项时,完整的 p4 仓库路径保留在 Git 中。例如,路径 '//depot/main/foo/bar.c' 从 '//depot/main/' 导入时变为 'foo/bar.c'。使用 --keep-path 时,Git 路径改为 'depot/main/foo/bar.c'。
--use-client-spec
:使用客户端规范在 p4 中查找感兴趣的文件列表。请参阅下面的"客户端规范"部分。
-/ <path>
:克隆或同步时排除选定的仓库路径。
Clone 选项
这些选项可在初始 'clone' 中使用,与上面描述的 'sync' 选项一起。
--destination <directory>
:在哪里创建 Git 仓库。如果未提供,使用 p4 仓库路径中的最后一个组件创建新目录。
--bare
:执行裸克隆。参见 git-clone(1)。
Submit 选项
这些选项可用于修改 'git p4 submit' 行为。
--origin <commit>
:标识要提交到 p4 的提交的上游位置。默认情况下,这是从 HEAD 可达的最近 p4 提交。
-M
:检测重命名。参见 git-diff(1)。重命名将在 p4 中使用显式 'move' 操作表示。没有相应的选项来检测复制,但移动和复制都有变量。
--preserve-user
:在提交到 p4 之前重新编写 p4 更改的作者。此选项需要 p4 管理员权限。
--export-labels
:将 Git 中的标签导出为 p4 标签。Git 中找到的标签应用于 perforce 工作目录。
-n, --dry-run
仅显示将提交到 p4 的提交;不更改 Git 或 p4 中的状态。
--prepare-p4-only
:将提交应用到 p4 工作区,像正常提交操作一样在 p4 中打开、添加和删除文件。不发出最终的 "p4 submit",而是打印关于如何手动提交或还原的消息。此选项始终在第一个(最旧的)提交后停止。Git 标签不会导出到 p4。
--shelve
:不是提交而是创建一系列搁置的更改列表。创建每个搁置后,相关文件被还原/删除。如果您有多个待处理的提交,将创建多个搁置。
--update-shelve CHANGELIST
:使用此提交更新现有的搁置更改列表。隐含 --shelve。对多个搁置更改列表重复。
--conflict=(ask|skip|quit)
:将提交应用到 p4 时可能发生冲突。发生这种情况时,默认行为("ask")是提示是跳过此提交并继续,还是退出。此选项可用于绕过提示,导致冲突的提交被自动跳过,或在不提示的情况下退出尝试应用提交。
--branch <branch>
:提交后,同步此命名的分支而不是默认的 p4/master。有关更多信息,请参阅上面的"Sync 选项"部分。
--commit (<sha1>|<sha1>..<sha1>)
:仅提交指定的提交或提交范围,而不是当前 Git 分支中的完整更改列表。
--disable-rebase
:在所有提交成功提交后禁用自动变基。也可以通过 git-p4.disableRebase 设置。
--disable-p4sync
:在提交后禁用从 Perforce 自动同步 p4/master。隐含 --disable-rebase。也可以通过 git-p4.disableP4Sync 设置。如果可能,仍会与 origin/master 同步。
提交钩子
p4-pre-submit
如果 p4-pre-submit 钩子存在且可执行,则会执行。该钩子不接受参数,也不从标准输入读取任何内容。从此脚本以非零状态退出会阻止 git-p4 submit 启动。可以使用 --no-verify 命令行选项绕过。
一个使用场景是在钩子中运行单元测试。
p4-prepare-changelist
p4-prepare-changelist 钩子在准备默认更改列表消息之后、编辑器启动之前执行。它接受一个参数,包含更改列表文本的文件名。从脚本以非零状态退出将中止过程。
该钩子的目的是就地编辑消息文件,不会被 --no-verify 选项抑制。即使设置了 --prepare-p4-only,也会调用此钩子。
p4-changelist
p4-changelist 钩子在用户编辑更改列表消息后执行。可以使用 --no-verify 选项绕过。它接受一个参数,保存提议的更改列表文本的文件名。以非零状态退出会导致命令中止。
该钩子可以编辑更改列表文件,可用于将文本规范化为某些项目标准格式。也可用于在检查消息文件后拒绝提交。
p4-post-changelist
p4-post-changelist 钩子在 P4 中成功提交后调用。它不接受参数,主要用于通知,不能影响 git p4 submit 操作的结果。
Rebase 选项
这些选项可用于修改 'git p4 rebase' 行为。
--import-labels
:导入 p4 标签。
Unshelve 选项
--origin
:设置与搁置的 P4 更改列表比较的 git refspec。默认为 p4/master。
仓库路径语法
'git p4 sync' 和 'git p4 clone' 的 p4 仓库路径参数可以是一个或多个以空格分隔的 p4 仓库路径,末尾可选的 p4 修订说明符:
"//depot/my/project"
:导入一个提交,包含该树下 '#head' 更改中的所有文件。
"//depot/my/project@all"
:为该仓库路径历史中的每个更改导入一个提交。
"//depot/my/project@1,6"
:仅导入更改 1 到 6。
"//depot/proj1@all //depot/proj2@all"
:将两个命名仓库路径中的所有更改导入单个仓库。仅包含这些目录下的文件。Git 中没有为每个 "proj1" 和 "proj2" 设置子目录。指定多个仓库路径时必须使用 --destination 选项。修订说明符必须在每个仓库路径上相同指定。如果仓库路径中有同名文件,最近更新版本的文件将出现在 Git 中。 有关 p4 修订说明符的完整语法,请参阅 'p4 help revisions'。
客户端规范
p4 客户端规范通过 'p4 client' 命令维护,包含除其他字段外一个 View,指定仓库如何映射到客户端仓库。'clone' 和 'sync' 命令在给出 --use-client-spec 选项或 useClientSpec 变量为 true 时可以查询客户端规范。'git p4 clone' 后,useClientSpec 变量自动设置在仓库配置文件中。这允许未来的 'git p4 submit' 命令正常工作;submit 命令仅查看变量,没有命令行选项。
p4 view 的完整语法记录在 'p4 help views' 中。'git p4' 仅了解 view 语法的一个子集。它理解多行映射、带 '+' 的覆盖、带 '-' 的排除和围绕空白的双引号。在可能的通配符中,'git p4' 仅处理 '...',且仅当它在路径末尾时。'git p4' 遇到未处理的通配符时会报错。
覆盖映射的实现存在错误。如果多个仓库路径通过覆盖映射到仓库中的同一位置,'git p4' 可能会选择错误的一个。这很难解决,除非专门为 'git p4' 设置客户端规范。
客户端名称可以通过多种方式给出给 'git p4'。变量 'git-p4.client' 如果存在则优先。否则,使用正常的 p4 机制确定客户端:环境变量 P4CLIENT、P4CONFIG 引用的文件或本地主机名。
分支检测
P4 没有与 Git 相同的分支概念。相反,p4 将其内容组织为目录树,按照约定不同的逻辑分支位于树中的不同位置。'p4 branch' 命令用于维护树中不同区域之间的映射,并指示相关内容。'git p4' 可以使用这些映射来确定分支关系。
如果您有一个仓库,其中所有感兴趣的分支都作为单个仓库路径的子目录存在,您可以在克隆或同步时使用 --detect-branches 让 'git p4' 自动查找 p4 中的子目录,并将它们生成为 Git 中的分支。
例如,如果 P4 仓库结构为:
//depot/main/...
//depot/branch1/...且 "p4 branch -o branch1" 显示如下 View 行:
//depot/main/... //depot/branch1/...那么这个 'git p4 clone' 命令:
git p4 clone --detect-branches //depot@all在 'refs/remotes/p4/' 中为 //depot/main 生成一个单独的分支,称为 'master',为 //depot/branch1 生成一个称为 'depot/branch1' 的分支。
但是,不必在 p4 中创建分支就能像使用分支一样使用它们。由于自动推断分支关系很困难,Git 配置设置 'git-p4.branchList' 可用于显式标识分支关系。它是 "source:destination" 对的列表,类似于简单的 p4 分支规范,其中 "source" 和 "destination" 是 p4 仓库中的路径元素。上面的示例依赖于 p4 分支的存在。没有 p4 分支,使用以下方式可以得到相同的结果:
git init depot
cd depot
git config git-p4.branchList main:branch1
git p4 clone --detect-branches //depot@all .性能
'git p4' 使用的快速导入机制为每次调用 'git p4 sync' 创建一个包文件。通常,Git 垃圾压缩(git-gc(1))会自动将这些压缩为更少的包文件,但显式调用 'git repack -adf' 可能会提高性能。
配置变量
以下配置设置可用于修改 'git p4' 行为。它们都在 'git-p4' 部分中。
通用变量
git-p4.user
:作为所有 p4 命令的选项指定的用户,使用 '-u <user>'。可以改用环境变量 P4USER。
git-p4.password
:作为所有 p4 命令的选项指定的密码,使用 '-P <password>'。可以改用环境变量 P4PASS。
git-p4.port
:作为所有 p4 命令的选项指定的端口,使用 '-p <port>'。可以改用环境变量 P4PORT。
git-p4.host
:作为所有 p4 命令的选项指定的主机,使用 '-h <host>'。可以改用环境变量 P4HOST。
git-p4.client
:作为所有 p4 命令的选项指定的客户端,使用 '-c <client>',包括客户端规范。
git-p4.retries
:指定 p4 命令(特别是 'p4 sync')在超时时的重试次数。默认值为 3。将值设置为 0 可禁用重试或您的 p4 版本不支持重试(2012.2 之前)。
Clone 和 sync 变量
git-p4.syncFromOrigin
:因为从其他 Git 仓库导入提交比从 p4 导入快得多,存在一种机制首先在 Git 远程中查找 p4 更改。如果分支存在于 'refs/remote/origin/p4' 下,这些将在从 p4 同步时被获取和使用。此变量可设置为 'false' 以禁用此行为。
git-p4.branchUser
:分支检测的一个阶段涉及查看 p4 分支以找到要导入的新分支。默认情况下,检查所有分支。此选项将搜索限制为仅变量中命名的单个用户拥有的分支。
git-p4.branchList
:启用分支检测时要导入的分支列表。每个条目应该是以冒号 (😃 分隔的分支名称对。此示例声明 branchA 和 branchB 都是从 main 创建的:
git config git-p4.branchList main:branchA
git config --add git-p4.branchList main:branchBgit-p4.ignoredP4Labels
:要忽略的 p4 标签列表。这是在发现不可导入的标签时自动构建的。
git-p4.importLabels
:按照 --import-labels 将 p4 标签导入 git。
git-p4.labelImportRegexp
:仅匹配此正则表达式的 p4 标签将被导入。默认值为 '[a-zA-Z0-9_-.]+$'。
git-p4.useClientSpec
:指定应使用 p4 客户端规范来标识感兴趣的 p4 仓库路径。这等同于指定选项 --use-client-spec。请参阅上面的"客户端规范"部分。此变量是布尔值,不是 p4 客户端的名称。
git-p4.pathEncoding
:Perforce 保留路径的编码。Git 期望路径编码为 UTF-8。使用此配置告诉 git-p4 Perforce 用于路径的编码。此编码用于将路径转码为 UTF-8。例如,Windows 上的 Perforce 通常使用 "cp1252" 编码路径名。如果此选项传递到 p4 clone 请求中,它将持久化到结果的新 git 仓库中。
git-p4.metadataDecodingStrategy
:Perforce 保留更改列表描述和用户全名的编码。p4v 客户端使用操作系统本地编码,因此不同用户最终可以在同一仓库中以不同编码存储不同的更改列表描述或用户全名。Git 容忍提交消息和作者名称中的不一致/不正确编码,但期望它们以 utf-8 指定。git-p4 在处理 Perforce 中的编码不确定性时可以使用三种不同的解码策略:'passthrough' 简单地将原始字节从 Perforce 传递到 git,当 Perforce 数据编码为 utf-8 以外的任何编码时创建可用但编码不正确的数据。'strict' 期望 Perforce 数据以 utf-8 编码,当不满足时导入失败。'fallback' 尝试将数据解释为 utf-8,否则回退使用辅助编码 - 默认为常见的 windows 编码 'cp-1252' - 如果使用回退编码解码也失败,则转义高位字节。在 python2 下,默认策略出于历史原因为 'passthrough',在 python3 下默认为 'fallback'。选择 'strict' 且解码失败时,错误消息将建议更改此配置参数作为解决方法。如果此选项传递到 p4 clone 请求中,它将持久化到结果的新 git 仓库中。
git-p4.metadataFallbackEncoding
:指定使用 'fallback' 策略解码 Perforce 作者名称和更改列表描述时使用的回退编码(参见 git-p4.metadataDecodingStrategy)。回退编码仅在 utf-8 解码失败时使用。此选项默认为 cp1252,一种常见的 windows 编码。如果此选项传递到 p4 clone 请求中,它将持久化到结果的新 git 仓库中。
git-p4.largeFileSystem
:指定用于大(二进制)文件的系统。请注意,大文件系统不支持 'git p4 submit' 命令。目前仅实现了 Git LFS(有关更多信息,请参阅 https://git-lfs.github.com/)。下载并安装 Git LFS 命令行扩展以使用此选项并像这样配置它:
git config git-p4.largeFileSystem GitLFSgit-p4.largeFileExtensions
:列表中匹配文件扩展名的所有文件将由大文件系统处理。不要在扩展名前加 '.'。
git-p4.largeFileThreshold
:未压缩大小超过阈值的所有文件将由大文件系统处理。默认阈值以字节为单位定义。添加后缀 k、m 或 g 以更改单位。
git-p4.largeFileCompressedThreshold
:压缩大小超过阈值的所有文件将由大文件系统处理。此选项可能会减慢您的克隆/同步过程。默认阈值以字节为单位定义。添加后缀 k、m 或 g 以更改单位。
git-p4.largeFilePush
:定义大文件是否自动推送到服务器的布尔变量。
git-p4.keepEmptyCommits
:如果此布尔选项设置为 true,仅包含排除文件的更改列表将作为空提交导入。
git-p4.mapUser
:将 P4 用户映射到 Git 中的名称和电子邮件地址。使用以下格式的字符串创建映射:
git config --add git-p4.mapUser "p4user = First Last <mail@address.com>"映射将覆盖来自 P4 的任何用户信息。可以定义多个 P4 用户的映射。
Submit 变量
git-p4.detectRenames
:检测重命名。参见 git-diff(1)。可以是 true、false 或 'git diff -M' 期望的分数。
git-p4.detectCopies
:检测复制。参见 git-diff(1)。可以是 true、false 或 'git diff -C' 期望的分数。
git-p4.detectCopiesHarder
:更努力地检测复制。参见 git-diff(1)。布尔值。
git-p4.preserveUser
:提交时,重新编写更改的作者以反映 Git 作者,无论谁调用 'git p4 submit'。
git-p4.allowMissingP4Users
:当 'preserveUser' 为 true 时,如果 'git p4' 无法在 p4 用户映射中找到作者,通常会终止。此设置无论如何都提交更改。
git-p4.skipSubmitEdit
:提交过程在每个 p4 更改提交之前调用编辑器。但如果此设置为 true,则跳过编辑步骤。
git-p4.skipSubmitEditCheck
:编辑 p4 更改消息后,'git p4' 通过查看文件修改时间确保描述确实已更改。此选项禁用该测试。
git-p4.allowSubmit
:默认情况下,任何分支都可以用作 'git p4 submit' 操作的源。此配置变量如果设置,仅允许命名的分支用作提交源。分支名称必须是短名称(不带 "refs/heads/"),并应以逗号 (",") 分隔,无空格。
git-p4.skipUserNameCheck
:如果运行 'git p4 submit' 的用户在 p4 用户映射中不存在,'git p4' 退出。此选项可用于强制提交而不考虑。
git-p4.attemptRCSCleanup
:如果启用,'git p4 submit' 将尝试清理 RCS 关键字($Header$ 等)。这些否则会导致合并冲突并阻止提交继续。此选项目前应视为实验性。
git-p4.exportLabels
:按照 --export-labels 将 Git 标签导出到 p4 标签。
git-p4.labelExportRegexp
:仅匹配此正则表达式的 p4 标签将被导出。默认值为 '[a-zA-Z0-9_-.]+$'。
git-p4.conflict
:按照 --conflict 指定发现 p4 冲突时的提交行为。默认行为为 'ask'。
git-p4.disableRebase
:提交后不要对 p4/master 进行变基。
git-p4.disableP4Sync
:提交后不要从 Perforce 同步 p4/master。隐含 git-p4.disableRebase。
实现细节
- 来自 p4 的更改集使用 Git 快速导入导入。
- 克隆或同步不需要 p4 客户端;文件内容使用 'p4 print' 收集。
- 提交需要 p4 客户端,它不在 Git 仓库的同一位置。补丁逐个应用到此 p4 客户端并从那里提交。
- 'git p4' 导入的每个提交在日志消息末尾都有一行,指示 p4 仓库位置和更改号。此行用于后续的 'git p4 sync' 操作以了解哪些 p4 更改是新的。
Git
git(1) 套件的一部分
