git-p4 - Perforce <-> Git converter using git-fast-import Usage ===== git-p4 can be used in two different ways: 1) To import changes from Perforce to a Git repository, using "git-p4 sync". 2) To submit changes from Git back to Perforce, using "git-p4 submit". Importing ========= Simply start with git-p4 clone //depot/path/project or git-p4 clone //depot/path/project myproject This will: 1) Create an empty git repository in a subdirectory called "project" (or "myproject" with the second command) 2) Import the head revision from the given Perforce path into a git branch called "p4" (remotes/p4 actually) 3) Create a master branch based on it and check it out. If you want the entire history (not just the head revision) then you can simply append a "@all" to the depot path: git-p4 clone //depot/project/main@all myproject If you want more control you can also use the git-p4 sync command directly: mkdir repo-git cd repo-git git init git-p4 sync //path/in/your/perforce/depot This will import the current head revision of the specified depot path into a "remotes/p4/master" branch of your git repository. You can use the --branch=mybranch option to import into a different branch. If you want to import the entire history of a given depot path simply use: git-p4 sync //path/in/depot@all Note: To achieve optimal compression you may want to run 'git repack -a -d -f' after a big import. This may take a while. Incremental Imports =================== After an initial import you can continue to synchronize your git repository with newer changes from the Perforce depot by just calling git-p4 sync in your git repository. By default the "remotes/p4/master" branch is updated. Advanced Setup ============== Suppose you have a periodically updated git repository somewhere, containing a complete import of a Perforce project. This repository can be cloned and used with git-p4. When updating the cloned repository with the "sync" command, git-p4 will try to fetch changes from the original repository first. The git protocol used with this is usually faster than importing from Perforce directly. This behaviour can be disabled by setting the "git-p4.syncFromOrigin" git configuration variable to "false". Updating ======== A common working pattern is to fetch the latest changes from the Perforce depot and merge them with local uncommitted changes. The recommended way is to use git's rebase mechanism to preserve linear history. git-p4 provides a convenient git-p4 rebase command that calls git-p4 sync followed by git rebase to rebase the current working branch. Submitting ========== git-p4 has support for submitting changes from a git repository back to the Perforce depot. This requires a Perforce checkout separate from your git repository. To submit all changes that are in the current git branch but not in the "p4" branch (or "origin" if "p4" doesn't exist) simply call git-p4 submit in your git repository. If you want to submit changes in a specific branch that is not your current git branch you can also pass that as an argument: git-p4 submit mytopicbranch You can override the reference branch with the --origin=mysourcebranch option. The Perforce changelists will be created with the user who ran git-p4. If you use --preserve-user then git-p4 will attempt to create Perforce changelists with the Perforce user corresponding to the git commit author. You need to have sufficient permissions within Perforce, and the git users need to have Perforce accounts. Permissions can be granted using 'p4 protect'. If a submit fails you may have to "p4 resolve" and submit manually. You can continue importing the remaining changes with git-p4 submit --continue Example ======= # Clone a repository git-p4 clone //depot/path/project # Enter the newly cloned directory cd project # Do some work... vi foo.h # ... and commit locally to gi git commit foo.h # In the meantime somebody submitted changes to the Perforce depot. Rebase your latest # changes against the latest changes in Perforce: git-p4 rebase # Submit your locally committed changes back to Perforce git-p4 submit # ... and synchronize with Perforce git-p4 rebase Configuration parameters ======================== git-p4.user ($P4USER) Allows you to specify the username to use to connect to the Perforce repository. git config [--global] git-p4.user public git-p4.password ($P4PASS) Allows you to specify the password to use to connect to the Perforce repository. Warning this password will be visible on the command-line invocation of the p4 binary. git config [--global] git-p4.password public1234 git-p4.port ($P4PORT) Specify the port to be used to contact the Perforce server. As this will be passed directly to the p4 binary, it may be in the format host:port as well. git config [--global] git-p4.port codes.zimbra.com:2666 git-p4.host ($P4HOST) Specify the host to contact for a Perforce repository. git config [--global] git-p4.host perforce.example.com git-p4.client ($P4CLIENT) Specify the client name to use git config [--global] git-p4.client public-view git-p4.allowSubmit git config [--global] git-p4.allowSubmit false git-p4.syncFromOrigin A useful setup may be that you have a periodically updated git repository somewhere that contains a complete import of a Perforce project. That git repository can be used to clone the working repository from and one would import from Perforce directly after cloning using git-p4. If the connection to the Perforce server is slow and the working repository hasn't been synced for a while it may be desirable to fetch changes from the origin git repository using the efficient git protocol. git-p4 supports this setup by calling "git fetch origin" by default if there is an origin branch. You can disable this using: git config [--global] git-p4.syncFromOrigin false git-p4.useclientspec git config [--global] git-p4.useclientspec false The P4CLIENT environment variable should be correctly set for p4 to be able to find the relevant client. This client spec will be used to both filter the files cloned by git and set the directory layout as specified in the client (this implies --keep-path style semantics). git-p4.skipSubmitModTimeCheck git config [--global] git-p4.skipSubmitModTimeCheck false If true, submit will not check if the p4 change template has been modified. git-p4.preserveUser git config [--global] git-p4.preserveUser false If true, attempt to preserve user names by modifying the p4 changelists. See the "--preserve-user" submit option. git-p4.allowMissingPerforceUsers git config [--global] git-p4.allowMissingP4Users false If git-p4 is setting the perforce user for a commit (--preserve-user) then if there is no perforce user corresponding to the git author, git-p4 will stop. With allowMissingPerforceUsers set to true, git-p4 will use the current user (i.e. the behavior without --preserve-user) and carry on with the perforce commit. git-p4.skipUserNameCheck git config [--global] git-p4.skipUserNameCheck false When submitting, git-p4 checks that the git commits are authored by the current p4 user, and warns if they are not. This disables the check. git-p4.detectRenames Detect renames when submitting changes to Perforce server. Will enable -M git argument. Can be optionally set to a number representing the threshold percentage value of the rename detection. git config [--global] git-p4.detectRenames true git config [--global] git-p4.detectRenames 50 git-p4.detectCopies Detect copies when submitting changes to Perforce server. Will enable -C git argument. Can be optionally set to a number representing the threshold percentage value of the copy detection. git config [--global] git-p4.detectCopies true git config [--global] git-p4.detectCopies 80 git-p4.detectCopiesHarder Detect copies even between files that did not change when submitting changes to Perforce server. Will enable --find-copies-harder git argument. git config [--global] git-p4.detectCopies true Implementation Details... ========================= * Changesets from Perforce are imported using git fast-import. * The import does not require anything from the Perforce client view as it just uses "p4 print //depot/path/file#revision" to get the actual file contents. * Every imported changeset has a special [git-p4...] line at the end of the log message that gives information about the corresponding Perforce change number and is also used by git-p4 itself to find out where to continue importing when doing incremental imports. Basically when syncing it extracts the perforce change number of the latest commit in the "p4" branch and uses "p4 changes //depot/path/...@changenum,#head" to find out which changes need to be imported. * git-p4 submit uses "git rev-list" to pick the commits between the "p4" branch and the current branch. The commits themselves are applied using git diff/format-patch ... | git apply