git-p4 - Man Page

Import from and submit to Perforce repositories

Examples (TL;DR)

Synopsis

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

Description

This command provides a way to interact with p4 repositories using Git​.

Create a new Git repository from an existing p4 repository using git p4 clone, giving it one or more p4 depot paths​. Incorporate new commits from p4 changes with git p4 sync​. The sync command is also used to include new branches from other p4 depot paths​. Submit Git changes back to p4 using git p4 submit​. The command git p4 rebase does a sync plus rebases the current branch onto the updated p4 remote branch​.

Examples

Commands

Clone

Generally, git p4 clone is used to create a new Git directory from an existing p4 repository:

$ git p4 clone //depot/path/project

This:

  1. Creates an empty Git repository in a subdirectory called project​.
  2. Imports the full contents of the head revision from the given p4 depot path into a single commit in the Git branch refs/remotes/p4/master​.
  3. Creates a local branch, master from this remote and checks it out​.

To reproduce the entire p4 history in Git, use the @all modifier on the depot path:

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

Sync

As development continues in the p4 repository, those changes can be included in the Git repository using:

$ git p4 sync

This command finds new changes in p4 and imports them as Git commits​.

P4 repositories can be added to an existing Git repository using git p4 sync too:

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

This imports the specified depot into refs/remotes/p4/master in an existing Git repository​. The --branch option can be used to specify a different branch to be used for the p4 content​.

If a Git repository includes branches refs/remotes/origin/p4, these will be fetched and consulted first during a git p4 sync​. Since importing directly from p4 is considerably slower than pulling changes from a Git remote, this can be useful in a multi-developer environment​.

If there are multiple branches, doing git p4 sync will automatically use the "Branch Detection" algorithm to try to partition new changes into the right branch​. This can be overridden with the --branch option to specify just a single branch to update​.

Rebase

A common working pattern is to fetch the latest changes from the p4 depot and merge them with local uncommitted changes​. Often, the p4 repository is the ultimate location for all code, thus a rebase workflow makes sense​. This command does git p4 sync followed by git rebase to move local commits on top of updated p4 changes​.

$ git p4 rebase

Submit

Submitting changes from a Git repository back to the p4 repository requires a separate p4 client workspace​. This should be specified using the P4CLIENT environment variable or the Git configuration variable git-p4​.client​. The p4 client must exist, but the client root will be created and populated if it does not already exist​.

To submit all changes that are in the current Git branch but not in the p4/master branch, use:

$ git p4 submit

To specify a branch other than the current one, use:

$ git p4 submit topicbranch

To specify a single commit or a range of commits, use:

$ git p4 submit --commit <sha1>
$ git p4 submit --commit <sha1​.​.sha1>

The upstream reference is generally refs/remotes/p4/master, but can be overridden using the --origin= command-line option​.

The p4 changes will be created as the user invoking git p4 submit​. The --preserve-user option will cause ownership to be modified according to the author of the Git commit​. This option requires admin privileges in p4, which can be granted using p4 protect​.

To shelve changes instead of submitting, use --shelve and --update-shelve:

$ git p4 submit --shelve
$ git p4 submit --update-shelve 1234 --update-shelve 2345

Unshelve

Unshelving will take a shelved P4 changelist, and produce the equivalent git commit in the branch refs/remotes/p4-unshelved/<changelist>​.

The git commit is created relative to the current origin revision (HEAD by default)​. A parent commit is created based on the origin, and then the unshelve commit is created based on that​.

The origin revision can be changed with the "--origin" option​.

If the target branch in refs/remotes/p4-unshelved already exists, the old one will be renamed​.

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

Options

General options

All commands except clone accept these options​.

--git-dir <dir>

Set the GIT_DIR environment variable​. See git(1)​.

-v,  --verbose

Provide more progress information​.

Sync options

These options can be used in the initial clone as well as in subsequent sync operations​.

--branch <ref>

Import changes into <ref> instead of refs/remotes/p4/master​. If <ref> starts with refs/, it is used as is​. Otherwise, if it does not start with p4/, that prefix is added​.

By default a <ref> not starting with refs/ is treated as the name of a remote-tracking branch (under refs/remotes/)​. This behavior can be modified using the --import-local option​.

The default <ref> is "master"​.

This example imports a new remote "p4/proj2" into an existing Git repository:

    $ git init
    $ git p4 sync --branch=refs/remotes/p4/proj2 //depot/proj2
--detect-branches

Use the branch detection algorithm to find new paths in p4​. It is documented below in "Branch Detection"​.

--changesfile <file>

Import exactly the p4 change numbers listed in file, one per line​. Normally, git p4 inspects the current p4 repository state and detects the changes it should import​.

--silent

Do not print any progress information​.

--detect-labels

Query p4 for labels associated with the depot paths, and add them as tags in Git​. Limited usefulness as only imports labels associated with new changelists​. Deprecated​.

--import-labels

Import labels from p4 into Git​.

--import-local

By default, p4 branches are stored in refs/remotes/p4/, where they will be treated as remote-tracking branches by git-branch(1) and other commands​. This option instead puts p4 branches in refs/heads/p4/​. Note that future sync operations must specify --import-local as well so that they can find the p4 branches in refs/heads​.

--max-changes <n>

Import at most n changes, rather than the entire range of changes included in the given revision specifier​. A typical usage would be use @all as the revision specifier, but then to use --max-changes 1000 to import only the last 1000 revisions rather than the entire revision history​.

--changes-block-size <n>

The internal block size to use when converting a revision specifier such as @all into a list of specific change numbers​. Instead of using a single call to p4 changes to find the full list of changes for the conversion, there are a sequence of calls to p4 changes -m, each of which requests one block of changes of the given size​. The default block size is 500, which should usually be suitable​.

--keep-path

The mapping of file names from the p4 depot path to Git, by default, involves removing the entire depot path​. With this option, the full p4 depot path is retained in Git​. For example, path //depot/main/foo/bar​.c, when imported from //depot/main/, becomes foo/bar​.c​. With --keep-path, the Git path is instead depot/main/foo/bar​.c​.

--use-client-spec

Use a client spec to find the list of interesting files in p4​. See the "Client Spec" section below​.

-/ <path>

Exclude selected depot paths when cloning or syncing​.

Clone options

These options can be used in an initial clone, along with the sync options described above​.

--destination <directory>

Where to create the Git repository​. If not provided, the last component in the p4 depot path is used to create a new directory​.

--bare

Perform a bare clone​. See git-clone(1)​.

Submit options

These options can be used to modify git p4 submit behavior​.

--origin <commit>

Upstream location from which commits are identified to submit to p4​. By default, this is the most recent p4 commit reachable from HEAD​.

-M

Detect renames​. See git-diff(1)​. Renames will be represented in p4 using explicit move operations​. There is no corresponding option to detect copies, but there are variables for both moves and copies​.

--preserve-user

Re-author p4 changes before submitting to p4​. This option requires p4 admin privileges​.

--export-labels

Export tags from Git as p4 labels​. Tags found in Git are applied to the perforce working directory​.

-n, --dry-run

Show just what commits would be submitted to p4; do not change state in Git or p4​.

--prepare-p4-only

Apply a commit to the p4 workspace, opening, adding and deleting files in p4 as for a normal submit operation​. Do not issue the final "p4 submit", but instead print a message about how to submit manually or revert​. This option always stops after the first (oldest) commit​. Git tags are not exported to p4​.

--shelve

Instead of submitting create a series of shelved changelists​. After creating each shelve, the relevant files are reverted/deleted​. If you have multiple commits pending multiple shelves will be created​.

--update-shelve CHANGELIST

Update an existing shelved changelist with this commit​. Implies --shelve​. Repeat for multiple shelved changelists​.

--conflict=(ask|skip|quit)

Conflicts can occur when applying a commit to p4​. When this happens, the default behavior ("ask") is to prompt whether to skip this commit and continue, or quit​. This option can be used to bypass the prompt, causing conflicting commits to be automatically skipped, or to quit trying to apply commits, without prompting​.

--branch <branch>

After submitting, sync this named branch instead of the default p4/master​. See the "Sync options" section above for more information​.

--commit (<sha1>|<sha1>​.​.<sha1>)

Submit only the specified commit or range of commits, instead of the full list of changes that are in the current Git branch​.

--disable-rebase

Disable the automatic rebase after all commits have been successfully submitted​. Can also be set with git-p4​.disableRebase​.

--disable-p4sync

Disable the automatic sync of p4/master from Perforce after commits have been submitted​. Implies --disable-rebase​. Can also be set with git-p4​.disableP4Sync​. Sync with origin/master still goes ahead if possible​.

Hooks for Submit

p4-pre-submit

The p4-pre-submit hook is executed if it exists and is executable​. The hook takes no parameters and nothing from standard input​. Exiting with non-zero status from this script prevents git-p4 submit from launching​. It can be bypassed with the --no-verify command line option​.

One usage scenario is to run unit tests in the hook​.

p4-prepare-changelist

The p4-prepare-changelist hook is executed right after preparing the default changelist message and before the editor is started​. It takes one parameter, the name of the file that contains the changelist text​. Exiting with a non-zero status from the script will abort the process​.

The purpose of the hook is to edit the message file in place, and it is not suppressed by the --no-verify option​. This hook is called even if --prepare-p4-only is set​.

p4-changelist

The p4-changelist hook is executed after the changelist message has been edited by the user​. It can be bypassed with the --no-verify option​. It takes a single parameter, the name of the file that holds the proposed changelist text​. Exiting with a non-zero status causes the command to abort​.

The hook is allowed to edit the changelist file and can be used to normalize the text into some project standard format​. It can also be used to refuse the Submit after inspect the message file​.

p4-post-changelist

The p4-post-changelist hook is invoked after the submit has successfully occurred in P4​. It takes no parameters and is meant primarily for notification and cannot affect the outcome of the git p4 submit action​.

Rebase options

These options can be used to modify git p4 rebase behavior​.

--import-labels

Import p4 labels​.

Unshelve options

--origin

Sets the git refspec against which the shelved P4 changelist is compared​. Defaults to p4/master​.

Depot Path Syntax

The p4 depot path argument to git p4 sync and git p4 clone can be one or more space-separated p4 depot paths, with an optional p4 revision specifier on the end:

"//depot/my/project"

Import one commit with all files in the #head change under that tree​.

"//depot/my/project@all"

Import one commit for each change in the history of that depot path​.

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

Import only changes 1 through 6​.

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

Import all changes from both named depot paths into a single repository​. Only files below these directories are included​. There is not a subdirectory in Git for each "proj1" and "proj2"​. You must use the --destination option when specifying more than one depot path​. The revision specifier must be specified identically on each depot path​. If there are files in the depot paths with the same name, the path with the most recently updated version of the file is the one that appears in Git​.

See p4 help revisions for the full syntax of p4 revision specifiers​.

Client Spec

The p4 client specification is maintained with the p4 client command and contains among other fields, a View that specifies how the depot is mapped into the client repository​. The clone and sync commands can consult the client spec when given the --use-client-spec option or when the useClientSpec variable is true​. After git p4 clone, the useClientSpec variable is automatically set in the repository configuration file​. This allows future git p4 submit commands to work properly; the submit command looks only at the variable and does not have a command-line option​.

The full syntax for a p4 view is documented in p4 help views​. git p4 knows only a subset of the view syntax​. It understands multi-line mappings, overlays with +, exclusions with - and double-quotes around whitespace​. Of the possible wildcards, git p4 only handles ​..., and only when it is at the end of the path​. git p4 will complain if it encounters an unhandled wildcard​.

Bugs in the implementation of overlap mappings exist​. If multiple depot paths map through overlays to the same location in the repository, git p4 can choose the wrong one​. This is hard to solve without dedicating a client spec just for git p4​.

The name of the client can be given to git p4 in multiple ways​. The variable git-p4​.client takes precedence if it exists​. Otherwise, normal p4 mechanisms of determining the client are used: environment variable P4CLIENT, a file referenced by P4CONFIG, or the local host name​.

Branch Detection

P4 does not have the same concept of a branch as Git​. Instead, p4 organizes its content as a directory tree, where by convention different logical branches are in different locations in the tree​. The p4 branch command is used to maintain mappings between different areas in the tree, and indicate related content​. git p4 can use these mappings to determine branch relationships​.

If you have a repository where all the branches of interest exist as subdirectories of a single depot path, you can use --detect-branches when cloning or syncing to have git p4 automatically find subdirectories in p4, and to generate these as branches in Git​.

For example, if the P4 repository structure is:

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

And "p4 branch -o branch1" shows a View line that looks like:

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

Then this git p4 clone command:

git p4 clone --detect-branches //depot@all

produces a separate branch in refs/remotes/p4/ for //depot/main, called master, and one for //depot/branch1 called depot/branch1​.

However, it is not necessary to create branches in p4 to be able to use them like branches​. Because it is difficult to infer branch relationships automatically, a Git configuration setting git-p4​.branchList can be used to explicitly identify branch relationships​. It is a list of "source:destination" pairs, like a simple p4 branch specification, where the "source" and "destination" are the path elements in the p4 repository​. The example above relied on the presence of the p4 branch​. Without p4 branches, the same result will occur with:

git init depot
cd depot
git config git-p4​.branchList main:branch1
git p4 clone --detect-branches //depot@all ​.

Performance

The fast-import mechanism used by git p4 creates one pack file for each invocation of git p4 sync​. Normally, Git garbage compression (git-gc(1)) automatically compresses these to fewer pack files, but explicit invocation of git repack -adf may improve performance​.

Configuration Variables

The following config settings can be used to modify git p4 behavior​. They all are in the git-p4 section​.

General variables

git-p4​.user

User specified as an option to all p4 commands, with -u <user>​. The environment variable P4USER can be used instead​.

git-p4​.password

Password specified as an option to all p4 commands, with -P <password>​. The environment variable P4PASS can be used instead​.

git-p4​.port

Port specified as an option to all p4 commands, with -p <port>​. The environment variable P4PORT can be used instead​.

git-p4​.host

Host specified as an option to all p4 commands, with -h <host>​. The environment variable P4HOST can be used instead​.

git-p4​.client

Client specified as an option to all p4 commands, with -c <client>, including the client spec​.

git-p4​.retries

Specifies the number of times to retry a p4 command (notably, p4 sync) if the network times out​. The default value is 3​. Set the value to 0 to disable retries or if your p4 version does not support retries (pre 2012​.2)​.

Clone and sync variables

git-p4​.syncFromOrigin

Because importing commits from other Git repositories is much faster than importing them from p4, a mechanism exists to find p4 changes first in Git remotes​. If branches exist under refs/remote/origin/p4, those will be fetched and used when syncing from p4​. This variable can be set to false to disable this behavior​.

git-p4​.branchUser

One phase in branch detection involves looking at p4 branches to find new ones to import​. By default, all branches are inspected​. This option limits the search to just those owned by the single user named in the variable​.

git-p4​.branchList

List of branches to be imported when branch detection is enabled​. Each entry should be a pair of branch names separated by a colon (:)​. This example declares that both branchA and branchB were created from main:

git config       git-p4​.branchList main:branchA
git config --add git-p4​.branchList main:branchB
git-p4​.ignoredP4Labels

List of p4 labels to ignore​. This is built automatically as unimportable labels are discovered​.

git-p4​.importLabels

Import p4 labels into git, as per --import-labels​.

git-p4​.labelImportRegexp

Only p4 labels matching this regular expression will be imported​. The default value is [a-zA-Z0-9_\-​.]+$​.

git-p4​.useClientSpec

Specify that the p4 client spec should be used to identify p4 depot paths of interest​. This is equivalent to specifying the option --use-client-spec​. See the "Client Spec" section above​. This variable is a boolean, not the name of a p4 client​.

git-p4​.pathEncoding

Perforce keeps the encoding of a path as given by the originating OS​. Git expects paths encoded as UTF-8​. Use this config to tell git-p4 what encoding Perforce had used for the paths​. This encoding is used to transcode the paths to UTF-8​. As an example, Perforce on Windows often uses "cp1252" to encode path names​. If this option is passed into a p4 clone request, it is persisted in the resulting new git repo​.

git-p4​.metadataDecodingStrategy

Perforce keeps the encoding of a changelist descriptions and user full names as stored by the client on a given OS​. The p4v client uses the OS-local encoding, and so different users can end up storing different changelist descriptions or user full names in different encodings, in the same depot​. Git tolerates inconsistent/incorrect encodings in commit messages and author names, but expects them to be specified in utf-8​. git-p4 can use three different decoding strategies in handling the encoding uncertainty in Perforce: passthrough simply passes the original bytes through from Perforce to git, creating usable but incorrectly-encoded data when the Perforce data is encoded as anything other than utf-8​. strict expects the Perforce data to be encoded as utf-8, and fails to import when this is not true​. fallback attempts to interpret the data as utf-8, and otherwise falls back to using a secondary encoding - by default the common windows encoding cp-1252 - with upper-range bytes escaped if decoding with the fallback encoding also fails​. Under python2 the default strategy is passthrough for historical reasons, and under python3 the default is fallback​. When strict is selected and decoding fails, the error message will propose changing this config parameter as a workaround​. If this option is passed into a p4 clone request, it is persisted into the resulting new git repo​.

git-p4​.metadataFallbackEncoding

Specify the fallback encoding to use when decoding Perforce author names and changelists descriptions using the fallback strategy (see git-p4​.metadataDecodingStrategy)​. The fallback encoding will only be used when decoding as utf-8 fails​. This option defaults to cp1252, a common windows encoding​. If this option is passed into a p4 clone request, it is persisted into the resulting new git repo​.

git-p4​.largeFileSystem

Specify the system that is used for large (binary) files​. Please note that large file systems do not support the git p4 submit command​. Only Git LFS is implemented right now (see https://git-lfs​.github​.com/ for more information)​. Download and install the Git LFS command line extension to use this option and configure it like this:

git config       git-p4​.largeFileSystem GitLFS
git-p4​.largeFileExtensions

All files matching a file extension in the list will be processed by the large file system​. Do not prefix the extensions with ​.​.

git-p4​.largeFileThreshold

All files with an uncompressed size exceeding the threshold will be processed by the large file system​. By default the threshold is defined in bytes​. Add the suffix k, m, or g to change the unit​.

git-p4​.largeFileCompressedThreshold

All files with a compressed size exceeding the threshold will be processed by the large file system​. This option might slow down your clone/sync process​. By default the threshold is defined in bytes​. Add the suffix k, m, or g to change the unit​.

git-p4​.largeFilePush

Boolean variable which defines if large files are automatically pushed to a server​.

git-p4​.keepEmptyCommits

A changelist that contains only excluded files will be imported as an empty commit if this boolean option is set to true​.

git-p4​.mapUser

Map a P4 user to a name and email address in Git​. Use a string with the following format to create a mapping:

git config --add git-p4​.mapUser "p4user = First Last <mail@address​.com>"

A mapping will override any user information from P4​. Mappings for multiple P4 user can be defined​.

Submit variables

git-p4​.detectRenames

Detect renames​. See git-diff(1)​. This can be true, false, or a score as expected by git diff -M​.

git-p4​.detectCopies

Detect copies​. See git-diff(1)​. This can be true, false, or a score as expected by git diff -C​.

git-p4​.detectCopiesHarder

Detect copies harder​. See git-diff(1)​. A boolean​.

git-p4​.preserveUser

On submit, re-author changes to reflect the Git author, regardless of who invokes git p4 submit​.

git-p4​.allowMissingP4Users

When preserveUser is true, git p4 normally dies if it cannot find an author in the p4 user map​. This setting submits the change regardless​.

git-p4​.skipSubmitEdit

The submit process invokes the editor before each p4 change is submitted​. If this setting is true, though, the editing step is skipped​.

git-p4​.skipSubmitEditCheck

After editing the p4 change message, git p4 makes sure that the description really was changed by looking at the file modification time​. This option disables that test​.

git-p4​.allowSubmit

By default, any branch can be used as the source for a git p4 submit operation​. This configuration variable, if set, permits only the named branches to be used as submit sources​. Branch names must be the short names (no "refs/heads/"), and should be separated by commas (","), with no spaces​.

git-p4​.skipUserNameCheck

If the user running git p4 submit does not exist in the p4 user map, git p4 exits​. This option can be used to force submission regardless​.

git-p4​.attemptRCSCleanup

If enabled, git p4 submit will attempt to cleanup RCS keywords ($Header$, etc)​. These would otherwise cause merge conflicts and prevent the submit going ahead​. This option should be considered experimental at present​.

git-p4​.exportLabels

Export Git tags to p4 labels, as per --export-labels​.

git-p4​.labelExportRegexp

Only p4 labels matching this regular expression will be exported​. The default value is [a-zA-Z0-9_\-​.]+$​.

git-p4​.conflict

Specify submit behavior when a conflict with p4 is found, as per --conflict​. The default behavior is ask​.

git-p4​.disableRebase

Do not rebase the tree against p4/master following a submit​.

git-p4​.disableP4Sync

Do not sync p4/master with Perforce following a submit​. Implies git-p4​.disableRebase​.

Implementation Details

Git

Part of the git(1) suite

Info

09/28/2026 Git 2.56.0 Git Manual