Distributed version control systems open up lots of flexibility and provide lots of efficiency in work-flow than their centralized cousins (e.g. Perforce). There’s often value to use DVCS in the team.
However, the case that I run into frequently is where there is a corporate standard for a deficient VCS, but the team wish to work efficiently by using a more powerful VCS. In that case, there are many successful stories of using multiple VCS: DVCS for local version control and committing to a shared centralized VCS with a DVCS-to-VCS bridge.
Git is particularly good at this aspect which provides tons of bridges to other VCS (That’s another good reason for preferring Git over Mercurial :-)). Lately I have been using the git-p4 bridge to synchronize codes between a centralized Perforce repository and a local Git repository. This post is a tutorial on how to set this up.
Setting up the Perforce command line client
- Install the p4 command line client (use MacPort or Homebrew if you are a Mac guy :-))
- Create a .p4settings file in your home directory with the global environment settings for your Perforce repository. And in your .bashrc, export P4CONFIG=/path/to/your/.p4settings. For example, here is what my settings look like:
P4PORT=repo_url:repo_port P4USER=user_name P4PASSWD=password P4CLIENT=client_workspace_name P4EDITOR=vim
- Run “p4 client” to define the workspace mappings
- Run “p4 info” to verify the settings
After you have done all these, don’t forget to issue “p4 sync repo_url” to test whether you are able to checkout stuff from your repository.
Installing git-p4 bridge
update 2014-02-25 git-p4 bridge has been moved to the top level git command. Use it as
git p4 instead of
The git-p4 bridge is a Python script to enable bidirectional operation between a Perforce depot and Git. It doesn’t come with the Git distribution by default. To make it invokable in your system, you need to download the script and put it into your system path. For me, I clone the Git source code from GitHub and make a soft-link to the script:
- Clone the Git repository to somewhere
git clone https://github.com/git/git.git git_source_path
- Create a soft-link to the git-p4 script in one of your system paths
ln -s git_source_path/contrib/fast-import/git-p4 /usr/bin/git-p4
Windows users need to include the git-p4.bat file in the system path.
Four things to remember when using git-p4:
- Instead of using “git push” to push local commits to remote repository, use “git-p4 submit”
- Instead of using “git fetch” to fetch changes from remote repository to local, use “git-p4 sync”
- Instead of using “git pull” to fetch and merge changes from remote repository to local, use “git-p4 rebase”
- Instead of using “git merge” to merge local branches, use “git rebase”
For the last one, the reason is that when you run “git merge”, Git creates an extra commit on top of the stack for the merging. This is not something we wanna show in the remote non-git repository. So we merge code with “git rebase”. Detailed explanation of the difference between git-merge and git-rebase goes here.
There is a detailed explanation on the usage of git-p4 in Git’s source. Here is an example almost covering daily usage:
- Login with “p4 login” and clone a Perforce project:
git-p4 clone //depot/path/project
- Make some changes to the project and commit locally to Git:
git commit changed_file
- In the meantime somebody in the team submitted changes to the remote Perforce repository. Merge it to your local repository:
- Submit your local changes back to Perforce:
Ignoring the .gitignore file
Normally we check in a .gitignore file to ignore files that we don’t want to check into the remote repository for each project. However, since the remote repository is not Git, it’s meaningless to check in this .gitignore file. To ignore this file, simply add an entry to .git/info/exclude.
Under the hook
There is no magic happening with git-p4. What it does is simply invoking the p4 command line tool to download sources to local, and then clone a Git repository out of it. You can simply verify this by typing “git branch -a”:
You may be amazed once again by how flexible the design of Git is which makes it possible to bridge to multiple VCS!
To quote Martin Fowler’s opinions on dual VCS, “a lot of teams can benefit from this dual-VCS working style, particularly if there’s a lot of corporate ceremony enforced by their corporate VCS. Using dual-VCS can often make both the local development team happier and the corporate controllers happier as their motivations for VCS are often different”.