## 命名

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 存储库交互的方式。

使用现有的 p4 存储库创建一个新的 Git 存储库`git p4 clone`，并为其提供一个或多个 p4 depot 路径。将 p4 更改中的新提交合并到`git p4 sync`。该`sync`命令还用于包含来自其他 p4 软件仓库路径的新分支。使用提交 Git 回到 p4 `git p4 submit`。该命令`git p4 rebase`执行 sync 并将当前分支重新绑定到更新的 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

这个：

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

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

3. `master`从这个远程创建一个本地分支并将其检出。

要在 Git 中重现整个 p4 历史记录，请`@all`在软件仓库路径中使用修饰符：

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

### Sync

随着 p4 存储库中的开发继续，可以使用以下方法将这些更改包含在 Git 存储库中：

    $ git p4 sync

该命令在 p4 中查找新的更改，并将它们作为 Git 提交导入。

P4 存储库也可以使用以下方式添加到现有的 Git 存储库`git p4 sync`：

    $ mkdir repo-git

    $ cd repo-git

    $ git init

    $ git p4 sync //path/in/your/perforce/depot

这会将指定的软件仓库导入到`refs/remotes/p4/master`现有的 Git 仓库中。该`--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 rebase

### Submit

将来自 Git 存储库的更改提交回 p4 存储库需要单独的 p4 客户端工作区。这应该使用`P4CLIENT`环境变量或 Git 配置变量来指定`git-p4.client`。p4 客户端必须存在，但如果客户端根目录尚不存在，它将被创建并填充。

要提交当前 Git 分支但不在分支中的所有更改`p4/master`，请使用：

    $ git p4 submit

要指定除当前分支以外的分支，请使用：

    $ git p4 submit topicbranch

上游引用通常是`refs/remotes/p4/master`，但可以使用`--origin=`命令行选项覆盖。

p4 的更改将在用户调用时创建`git p4 submit`。该`--preserve-user`选项将根据 Git 提交的作者来修改所有权。此选项需要 p4 中的管理员权限，可以使用该权限授予`p4 protect`。

## 选项

### 常规选项

除克隆以外的所有命令均接受这些选项

--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>

准确导入列出的 p4 更改编号`file`，每行一个。通常，`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`与上述`sync`选项一起使用。

--destination <directory>

在哪里创建 Git 存储库。如果未提供，则使用 p4 depot 路径中的最后一个组件创建新目录。

--bare

执行克隆空项。参见 git-clone [1] 。

### 提交选项

这些选项可以用来修改`git p4 submit`行为。

--origin <commit>

确认提交到 p4 的上游位置。默认情况下，这是可从中获得的最新 p4 提交`HEAD`。

-M

检测重命名。参见 git-diff [1] 。重命名将使用显式`move`操作在 p4 中表示。没有对应的选项来检测副本，但移动和副本都有变量。

--preserve-user

在提交给 p4 之前，重新创建 p4 更改。该选项需要 p4 管理员权限。

--export-labels

从 Git 导出标签作为 p4 标签。在 Git 中找到的标签应用于 perforce 工作目录。

-n --dry-run

显示将提交给 p4 的提交; 不要在 Git 或 p4 中更改状态。

--prepare-p4-only

将提交应用于 p4 工作区，在 p4 中打开，添加和删除文件，就像正常的提交操作一样。不要发布最终的“ p4 提交”，而是要打印一条关于如何手动提交或回复的消息。该选项总是在第一个（最早的）提交之后停止。Git 标签不会导出到 p4 。

--shelve

而不是提交创建一系列搁置的更改表。创建每个搁置后，相关文件将被还原/删除。如果您有多个提交，则会创建多个搁板。

--update-shelve CHANGELIST

使用此提交更新现有的搁置更改列表。意味着 --shelve。

--conflict=(ask|skip|quit)

将提交应用于 p4 时可能会发生冲突。发生这种情况时，默认行为（“询问”）是提示是否跳过此提交并继续或退出。此选项可用于绕过提示，导致提交冲突自动跳过，或退出尝试提交而不提示。

--branch <branch>

提交后，同步该命名分支，而不是默认的 p4 / master 。有关更多信息，请参阅上面的“同步选项”一节。

### 改变选项

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

--import-labels

导入 p4 标签。

## 仓库路径语法

p4 的贮库路径参数`git p4 sync`和`git p4 clone`可以是一个或多个空格分隔 P4 贮库的路径，与在端部的可选 P4 修订说明符：

"//depot/my/project"

`#head`在树下的更改中导入一个具有所有文件的提交。

"//depot/my/project@all"

为该软件仓库路径的历史记录中的每个更改导入一个提交。

"//depot/my/project@1,6"

只导入更改1到6。

"//depot/proj1@all //depot/proj2@all"

将来自两个指定软件仓库路径的所有更改导入单个存储库。只包含这些目录下的文件。每个 “proj1” 和 “proj2” 在 Git 中都没有一个子目录。`--destination`指定多个软件仓库路径时必须使用该选项。修订说明符必须在每个软件仓库路径上指定相同。如果软件仓库路径中有相同名称的文件，则具有该文件最近更新版本的路径就是出现在 Git 中的路径。

请参阅`p4 help revisions` p4 修订说明符的完整语法。

## 客户端规格

p4 客户端规范是使用该`p4 client`命令维护的，并在其他字段中包含一个视图，指定仓库如何映射到客户端存储库。在`clone`与`sync`给定的命令时，可以咨询客户规范`--use-client-spec`选项，或当 useClientSpec 变量为真。之后`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 机制：环境变量 P4CLIENT ，由 P4CONFIG 引用的文件或本地主机名。

## 分支检测

P4 与 Git 没有相同的分支概念。相反，p4将其内容组织为目录树，根据约定，不同的逻辑分支位于树中的不同位置。该`p4 branch`命令用于维护树中不同区域之间的映射，并指示相关内容。`git p4`可以使用这些映射来确定分支关系。

如果您有一个存储库，其中所有感兴趣的分支都作为单个软件仓库路径的子目录存在，则可以`--detect-branches`在克隆或同步时使用`git p4`自动在 p4 中查找子目录，并在 Git 中将其作为分支生成。

例如，如果 P4 存储库结构是：

    //depot/main/...//depot/branch1/...

并且“p4 分支 - o 分支1”显示一个 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-p4.branchList`因此可以使用 Git 配置设置来明确标识分支关系。它是一个 “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 sync`网络超时的情况下重试 p4 命令（特别是）的次数。默认值为3.将该值设置为0以禁用重试，或者如果您的 p4版本不支持重试（2012年之前）。

### 克隆和同步变量

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 仓库路径。这相当于指定选项`--use-client-spec`。请参阅上面的“客户端规格”部分。这个变量是一个布尔值，而不是 p4 客户端的名字。

git-p4.pathEncoding

Perforce 保留原始操作系统给定的路径编码。Git 预计编码为 UTF-8 的路径。使用此配置来告诉 git-p4 Perforce 用于路径的编码。此编码用于将路径转码为 UTF-8 。例如，Windows 上的 Perforce 通常使用 “cp1252” 来编码路径名称。

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] 。这可能是真实的，错误的，或者如预期的那样`git diff -M`。

git-p4.detectCopies

检测副本。参见 git-diff [1] 。这可能是真实的，错误的，或者如预期的那样`git diff -C`。

git-p4.detectCopiesHarder

更难检测副本。参见 git-diff [1] 。一个布尔值。

git-p4.preserveUser

在提交时，无论谁调用，都要重新编写更改以反映 Git 作者`git p4 submit`。

git-p4.allowMissingP4Users

如果`preserveUser`属实，`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 中的更改集。

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

- 提交需要一个与 Git 存储库不在同一位置的 p4 客户端。修补程序一次一个地应用于此 p4 客户端并从那里提交。

- 导入的每个提交`git p4`在日志消息末尾都有一行指示 p4 仓库位置和更改编号。此行被以后的`git p4 sync`操作用于了解哪些 p4 更改是新的。