Helix Core is now P4. Product user interfaces will be updated soon. Learn more >>

P4 Server Administration Documentation | 2026.1

# Triggering on submit and populate

To configure P4 Server to run trigger scripts when users submit changelists, use submit triggers: these are triggers of type `change-submit`, `change-content`, and `change-commit`.

You can also use `change-failed` triggers for the `p4 submit` or the `p4 populate` command.

The p4 populate command branches a set of files (the source) into another depot location (the target) in a single step. Therefore, to access the files of a change being submitted by p4 populate, use a `change-content` trigger (see Change-content triggers) and the p4 files @=change command. (In the case of p4 populate, a `change-content` trigger is equivalent to a `change-submit` trigger because no file transfer takes place from the client.)

Change-submit triggers can use the %command% trigger script variable to ignore populate commands (%command% == user-populate) so that `change-content` triggers can process p4 populate commands.

## File locking behavior associated with submits:

Before committing a changelist, `p4 submit` briefly locks all files being submitted. If any file cannot be locked or submitted, the files are left open in a numbered pending changelist. By default, the files in a failed submit operation are left locked unless the `submit.unlocklocked` configurable is set. If submit fails when `submit.unlocklocked` is set, files are unlocked even if they were manually locked prior to submit.

## The fields of a submit trigger

The following table describes the fields of a submit trigger. For sample definitions, see the subsequent sections, describing each trigger subtype.

Field | Meaning
--- | ---
`name` | The name of the submit trigger.
`type` | The event that causes the trigger to fire. change-submit: Execute a submit trigger after changelist creation, but before file transfer. Trigger cannot access file contents. See Change-submit triggers. change-content: Execute a submit trigger after changelist creation and file transfer, but before file commit. To obtain file contents, use the revision specifier `@=change` (where `change` is the changelist number of the pending changelist as passed to the script in the `%changelist%` variable) with commands such as `p4 diff2`, `p4 files`, `p4 fstat`, and `p4 print`. See Change-content triggers. change-commit: Execute a submit trigger after changelist creation, file transfer, and changelist commit. See Change-commit triggers. change-failed: Execute a submit trigger if the `p4 submit` or the `p4 populate` command fails. This trigger only fires on errors that occur after a commit process has started. It does not fire for early usage errors, or due to errors from the submit form. If an edge or change trigger could have run, the `change-failed` trigger will fire if that commit fails. See Change-failed triggers. `edge-submit`: Executes a pre-submit trigger on the edge server after changelist has been created, but prior to file transfer from the client to the edge server. The files are not necessarily locked at this point. See Triggers and commit-edge. `edge-content`: Executes a mid-submit trigger on the edge server after file transfer from the client to the edge server, but prior to file transfer from the edge server to the commit server. At this point, the changelist is shelved. See Triggers and commit-edge. When using `p4 diff2` in a `change-content` trigger: The first file argument can be either `file@change` or `file#headrev`, but NOT `file@=change`. The second file argument (typically the change being submitted) must use the `file@=change` syntax to report differences successfully. (Using `file@change` without the equals sign reports the file revisions as identical, which is wrong.) For example, to submit a file `//depot/foo` as change 1001, and the previously submitted change was 1000, with a head revision of 25, both these revision specifier formats should work correctly if generated and called in the trigger script:
      p4 diff2 //depot/foo@1000 file@=1001
`path` | A file pattern in depot syntax. When a user submits a changelist that contains any files that match this file pattern, the trigger specified in the `command` field is run. Use exclusionary mappings to prevent triggers from running on specified files.
`command` | The trigger for P4 Server to run when a user submits a changelist that contains any file patterns specified by `path`. Specify the command in a way that allows the P4 Server account to locate and run the command. The `command` (typically a call to a script) must be quoted, and can take as arguments anything that your `command` is capable of parsing, including any applicable P4 Server trigger variables. When your trigger script is stored in the depot, its path must be specified in depot syntax, delimited by percent characters. For example, if your script is stored in the depot as `//depot/scripts/myScript.pl`, the corresponding value for the command field might be `"/usr/bin/perl %//depot/scripts/myScript.pl%"`. See Storing triggers in the depot for more information. For `change-submit` and `change-content` triggers (and their corresponding edge server triggers), changelist submission does not continue if the trigger fails. For `change-commit` triggers, changelist submission succeeds regardless of trigger success or failure, but subsequent `change-commit` triggers do not fire if the script fails.

Even when a `change-submit` or `change-content` trigger script succeeds, the submit can fail because of subsequent trigger failures, or for other reasons. Use `change-submit` and `change-content` triggers only for validation, and use `change-commit` triggers for operations that are contingent on the successful completion of the submit.

Be aware of edge cases. For example, if a client workspace has the `revertunchanged` option set, and a user runs `p4 submit` on a changelist with no changed files, a changelist has been submitted with files contents, but no changes are actually committed. In this case, a `change-submit` trigger fires, a `change-content` trigger fires, but a `change-commit` trigger does not.

Your search for returned results