English ▾ 主题 ▾ 最新版本 ▾ git-p4 上次更新于 2.37.0

名称

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 depot 路径。使用 git p4 sync 合并来自 p4 更改的新提交。sync 命令也用于包含来自其他 p4 depot 路径的新分支。使用 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

命令

克隆

通常,git p4 clone 用于从现有的 p4 仓库创建一个新的 Git 目录

$ git p4 clone //depot/path/project

此命令

  1. 在名为 project 的子目录中创建一个空的 Git 仓库。

  2. 将给定 p4 depot 路径的头部修订的完整内容导入到 Git 分支 refs/remotes/p4/master 中的单个提交中。

  3. 从该远程创建一个本地分支 master 并检出它。

要在 Git 中重现整个 p4 历史,请在 depot 路径上使用 @all 修饰符

$ git p4 clone //depot/path/project@all

同步

随着 p4 仓库中开发的继续,可以使用以下命令将这些更改包含在 Git 仓库中

$ git p4 sync

此命令查找 p4 中的新更改并将其作为 Git 提交导入。

也可以使用 git p4 sync 将 P4 仓库添加到现有的 Git 仓库

$ mkdir repo-git
$ cd repo-git
$ git init
$ git p4 sync //path/in/your/perforce/depot

这将指定的 depot 导入到现有 Git 仓库中的 refs/remotes/p4/master 中。--branch 选项可用于指定用于 p4 内容的不同分支。

如果 Git 仓库包含分支 refs/remotes/origin/p4,则在 git p4 sync 期间将首先获取和参考这些分支。由于直接从 p4 导入比从 Git 远程拉取更改要慢得多,因此这在多开发者环境中很有用。

如果有多个分支,执行 git p4 sync 将自动使用“分支检测”算法尝试将新更改划分到正确的分支中。可以使用 --branch 选项覆盖此设置,以指定要更新的单个分支。

变基

一种常见的工作模式是从 p4 depot 获取最新更改,并将它们与本地未提交的更改合并。通常,p4 仓库是所有代码的最终位置,因此变基工作流是有意义的。此命令执行 git p4 sync,然后执行 git rebase 以将本地提交移动到更新的 p4 更改之上。

$ git p4 rebase

提交

要将 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 2345

取消暂缓

取消暂缓将采用暂缓的 P4 变更列表,并在分支 refs/remotes/p4-unshelved/<变更列表> 中生成等效的 git 提交。

git 提交是相对于当前 origin 修订版(默认为 HEAD)创建的。基于 origin 创建父提交,然后基于该提交创建取消暂缓提交。

可以使用 "--origin" 选项更改 origin 修订版。

如果 refs/remotes/p4-unshelved 中的目标分支已经存在,则将重命名旧分支。

$ git p4 sync
$ git p4 unshelve 12345
$ git show p4-unshelved/12345
<submit more changes via p4 to the same files>
$ git p4 unshelve 12345
<refuses to unshelve until git is in sync with p4 again>

选项

通用选项

除了 clone 之外的所有命令都接受这些选项。

--git-dir <dir>

设置 GIT_DIR 环境变量。请参阅 git[1]

-v
--verbose

提供更多进度信息。

同步选项

这些选项可以在初始 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 以获取与 depot 路径关联的标签,并将它们作为 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 depot 路径到 Git 的文件名映射涉及删除整个 depot 路径。使用此选项,完整的 p4 depot 路径将保留在 Git 中。例如,路径 //depot/main/foo/bar.c,从 //depot/main/ 导入时,变为 foo/bar.c。使用 --keep-path,Git 路径改为 depot/main/foo/bar.c

--use-client-spec

使用客户端规范来查找 p4 中感兴趣的文件列表。请参阅下面的“客户端规范”部分。

-/ <path>

克隆或同步时排除选定的 depot 路径。

克隆选项

这些选项可以与上面描述的 sync 选项一起在初始 clone 中使用。

--destination <directory>

在何处创建 Git 仓库。如果未提供,则 p4 depot 路径中的最后一个组件用于创建新目录。

--bare

执行裸克隆。请参阅 git-clone[1]

提交选项

这些选项可以用来修改 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。有关更多信息,请参见上面的“同步选项”部分。

--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 提交操作的结果。

变基选项

这些选项可以用来修改 git p4 rebase 的行为。

--import-labels

导入 p4 标签。

取消暂存选项

--origin

设置用于比较暂存的 P4 变更列表的 git refspec。默认为 p4/master。

仓库路径语法

git p4 syncgit 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,用于指定仓库如何映射到客户端存储库中。当给定 --use-client-spec 选项或 useClientSpec 变量为 true 时,clonesync 命令可以查阅客户端规范。在 git p4 clone 之后,useClientSpec 变量会自动设置在存储库配置文件中。这允许将来的 git p4 submit 命令正常工作;提交命令仅查看变量,没有命令行选项。

p4 视图的完整语法记录在 p4 help views 中。git p4 仅了解视图语法的一个子集。它理解多行映射、带有 + 的覆盖、带有 - 的排除以及空格周围的双引号。在可能的通配符中,git p4 仅处理 …​,并且仅当它位于路径的末尾时。如果 git p4 遇到未处理的通配符,它将发出抱怨。

重叠映射的实现中存在错误。如果多个仓库路径通过覆盖映射到存储库中的同一位置,则 git p4 可能会选择错误的路径。如果没有专门为 git p4 创建客户端规范,则很难解决此问题。

可以将客户端的名称以多种方式提供给 git p4。变量 git-p4.client 如果存在则优先。否则,使用确定客户端的普通 p4 机制:环境变量 P4CLIENTP4CONFIG 引用的文件或本地主机名。

分支检测

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 使用的 fast-import 机制为每次调用 git p4 sync 创建一个 pack 文件。通常,Git 垃圾压缩 (git-gc[1]) 会自动将它们压缩为更少的 pack 文件,但是显式调用 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。如果您的 p4 版本不支持重试(pre 2012.2),则将值设置为 0 以禁用重试。

克隆和同步变量

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:branchB
git-p4.ignoredP4Labels

要忽略的 p4 标签的列表。 这是在发现无法导入的标签时自动构建的。

git-p4.importLabels

根据 --import-labels 将 p4 标签导入到 git 中。

git-p4.labelImportRegexp

只会导入与此正则表达式匹配的 p4 标签。 默认值为 [a-zA-Z0-9_\-.]+$

git-p4.useClientSpec

指定应使用 p4 客户端规范来标识感兴趣的 p4 depot 路径。 这等效于指定选项 --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 客户端使用操作系统本地编码,因此不同的用户最终可能会在同一 depot 中以不同的编码存储不同的变更列表描述或用户全名。 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 策略(请参阅 git-p4.metadataDecodingStrategy)解码 Perforce 作者姓名和变更列表描述时,指定要使用的回退编码。 仅当作为 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 GitLFS
git-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 用户的映射。

提交变量

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

指定发现与 p4 冲突时的提交行为,如 --conflict 所示。 默认行为是 ask

git-p4.disableRebase

提交后,不要针对 p4/master 变基树。

git-p4.disableP4Sync

提交后,不要将 p4/master 与 Perforce 同步。 意味着 git-p4.disableRebase。

实现细节

  • 来自 p4 的变更集使用 Git fast-import 导入。

  • 克隆或同步不需要 p4 客户端; 文件内容是使用 p4 print 收集的。

  • 提交需要一个 p4 客户端,它与 Git 仓库不在同一位置。 补丁一次一个地应用于此 p4 客户端,并从那里提交。

  • git p4 导入的每个提交在日志消息的末尾都有一行,指示 p4 depot 位置和变更编号。 以后的 git p4 sync 操作使用此行来了解哪些 p4 更改是新的。

GIT

属于 git[1] 套件的一部分

scroll-to-top