Coping with Perforce using git-p4

 · 4 mins read

Coping with Perforce using git-p4

Some companies still use Perforce for version control. While Perforce can have some advantages, developers who have used git might find the Perforce workflow more painful.

Perforce pain points

  • No lightweight branching to keep changes separate
    • git makes it very easy to go between different sets of changes before they’re ready to push upstream
  • You have to tell Perforce every time you edit, add, or delete a file
    • git figures this out for you, and git status will show you your uncommitted changes
  • With git reflog, it’s almost impossible to lose your changes if you committed them at some point
  • You can count on git to fully revert your changes if you ask it to
    • Perforce ignores changes it doesn’t know about during reverts
  • More tooling supports git
    • JetBrains IDEs support Perforce, but niche tools like shell integration or Neovim have more options for git

Introducing git-p4

Getting started

The official documentation does a pretty good job of describing the basics. As it mentions, you can start with git p4 clone //depot/path/project@all. Unless your Perforce repository is truly enormous, I strongly suggest using the @all at the end to pull your entire history. This lets you use goodies like git blame to see when a line changed and by who.

For extra setup, I also copy the .p4ignore to a .gitignore, and add:

depot/ # Perforce or git-p4 seems to make this directory sometimes
.gitignore # I don't check in my .gitignore to avoid confusing other Perforce users
.reviewboardrc # If you end up adding one, see below

At work, we use reviewboard for code reviews, which can become confused when both Perforce and git are in use. Adding the following to my .reviewboardrc (or creating one if it doesn’t exit with these contents) fixed it for me:

REVIEWBOARD_URL = "reviewboard-server.com"
REPOSITORY_TYPE = "perforce"

My workflow

My usual workflow looks like this:

  1. Make sure I am on main/master with no uncommitted files
  2. I run git p4 sync to make sure I have the latest code, if Perforce nags me about open files, I run p4 revert //...
  3. I check out a new git branch for my work with git checkout -b my-new-feature. I never make commits on main so that I know that every commit on main has come from Perforce and is what’s currently checked in upstream
  4. I make the changes needed for my feature. For a quick example, we can run echo "hello world" > feature.txt.
  5. Now, I commit my change in git. I use git commit -am "My feature" but you can do this in a number of ways, including inside of your IDE.
  6. If you wish, you can set up pre-commit to run a linter on commit so your changes are squeaky clean. But we won’t go into that right now.
  7. If you don’t use review board, you can skip this step. For reviewboard, I first need to shelve my changes: git p4 submit --shelve HEAD which will give me a changeset number. Then, I will rbt post 1234 or whatever the changeset number is.
  8. When I get some feedback, I can git p4 unshelve 1234 (then check out the resulting branch it makes) and then I can incorporate the feedback and redo the above steps.
  9. Finally, when it is ready to submit, I can run git p4 submit HEAD.

To keep track of my shelved changesets, I use p4 changes -s shelved -u $USER.

Aliases for the above

You can run the following in your repository to add aliases for some of the useful git-p4 commands (this can go in your .profile, .bashrc, etc):

# Sync with the latest changes
alias gpl="git p4 sync";
# Stop Perforce complaints about open files (after committing your changes!)
alias gpr="p4 revert //...";
# List shelved changesets
alias gpls="p4 changes -s shelved -u mmcmillan";
# Delete a shelved changeset
alias gprms="p4 shelved -d -c";
# Shelve latest commit
alias gpsv="git p4 submit --shelve HEAD";
# Unshelve some changeset
alias gpus="git p4 unshelve";

Thinking about the future

Since the entire contents of your Perforce project is now stored in a git repository, a migration to use git in the future is as simple as git push to wherever you want to host your code. Often, Perforce is used for historical reasons, not because it’s the best option right now.