Perforce

08 Apr 2014

Until now, I’ve only really used distributed version control software; Mercurial in college and Git since I got a Github account. I started working at Cisco and started using Perforce. It’s been a little weird, but I think I’m getting the hang of it.

My Environment

I set Perforce’s P4CONFIG variable in my .bashrc to let me put a config file at the root of each of my Perforce repositories. This let’s me easily change my server, username, client, etc. for each repository. At work I like to have a client for each branch we work on; this lets me do just that.

My Perforce settings in my .bashrc

# Perforce
export P4CONFIG=.p4config
export P4IGNORE=.p4ignore
export P4EDITOR=vim

You might have noticed the P4IGNORE variable in my .bashrc.

P4IGNORE files work just like .gitignore.

One of my .p4config files

P4PORT=workshop.perforce.com:1666
P4USER=zachwhaley
P4CLIENT=project

Bash Completion

The bash completion in Git is really convenient, but unfortunately Perforce’s CLI program doesn’t come with a bash completion script. So I made my own.

Distributing Perforce

Perforce is not a distributed version control system (unless you’ve upgraded to Perforce Helix, in which case you should be using the Git integration), but there are ways to make it seem like it is.

Write All the Files!

So the Perforce settings at my work force all local files to be readonly by default. I feel like this hinders my programming flow and is just unnecessary. So I changed it.

The option to make all files writeable is in your Perforce client, which can be viewed with the following command.

$ p4 client

This will open your client settings in an editor to be viewed and changed. If you don’t like the default editor you can change this by setting the Perforce variable P4EDITOR in your bash environment, like below. This can also be set in your .bashrc like I did above.

$ export P4EDITOR=vim # For Unix users
$ p4 set P4EDITOR=vim # For (Mac)OSX users
$ p4 client

In the client settings, change the Option noallwrite to allwrite, and save the file.

# A Perforce Client Specification.
# ...
# A bunch of stuff is here

Client:	project

Update:	2014/04/07 15:32:56

Access:	2014/04/07 19:57:03

Owner:	zachwhaley

Host:	zachs-computer

Description:
	Created by zachwhaley.

Root:	/project

Options:	allwrite noclobber nocompress unlocked nomodtime normdir

SubmitOptions:	submitunchanged

LineEnd:	local

View:
	//depot/zachwhaley/project/... //project/...

This will save the client settings, but your files won’t become writeable just yet.

Perform a complete sync to update all your repository’s file’s permissions.

# Make sure any uncomitted changes to the repo are saved off somehow,
# before executing the next step.
$ cd /to/root/of/repo/
$ p4 sync -f ... # The ... means do this recursively starting here

You can now change any file you want! But what happens when It’s time to commit a change?

Reconcile with Lord Server

After I’ve made my changes to the code (for better or worse), I’ll run p4 status.

Just like Git, this command tells you what has been modified, added, or deleted from the server’s code base.

$ p4 status
bar.cpp - reconcile to add //depot/zachwhaley/project/bar.cpp#1
bar.hpp - reconcile to add //depot/zachwhaley/project/bar.hpp#1
foo.cpp - reconcile to edit //depot/zachwhaley/project/foo.cpp#2

Unlike Git, Perforce has no idea how the files changed, only that these files are different from the server’s files.

I still have to tell Lord Server which files I want to change and how. Since I’m happy with the files listed, it is time to reconcile with Lord Server and tell them what I have done.

$ p4 reconcile
//depot/zachwhaley/project/bar.cpp#1 - opened for add
//depot/zachwhaley/project/bar.hpp#1 - opened for add
//depot/zachwhaley/project/foo.cpp#2 - opened for edit

Perforce has now opened (checked out) the files for me.

Use p4 opened To see a list of your open files. And p4 diff to see code changes for open files

$ p4 opened
//depot/zachwhaley/project/bar.cpp#1 - add default change (text)
//depot/zachwhaley/project/bar.hpp#1 - add default change (text)
//depot/zachwhaley/project/foo.cpp#2 - edit default change (text)
$ p4 diff foo.cpp
==== //depot/zachwhaley/project/foo.cpp#2 - /project/foo.cpp ====
33a34,42
> // p4 ain't that bad

Change, Submit, and Go Home

When I’m finally ready to commit my code, I create a change.

I use Perforce changes like Git staging. They are similar in that they identify what is going to change, without actually making the change happen. They are not similar in that I have to create a change description (commit message) when creating the change. Don’t worry though, this description can be changed before submission

p4 change will open an editor where I add my description and specify which files go with this change.

$ p4 change
# A Perforce Change Specification.
# ...
# A bunch of stuff is here

Change:	new

Client:	project

User:	zachwhaley

Status:	new

Description:
	<enter description here>

Files:
    //depot/zachwhaley/project/bar.cpp # add
    //depot/zachwhaley/project/bar.hpp # add
    //depot/zachwhaley/project/foo.cpp # edit

A change number will be printed after I save my new change.

$ p4 change
Change 1010 created with 3 open file(s).

This number uniquely identifies this change and can be used to edit the change description, add or remove files to the change, etc.

$ p4 change 1010 # Edit change 1010
$ p4 revert -c 1010 somedir/* # Reverts files in somedir that belong to change 1010
$ p4 edit -c 1010 perf.py # Adds a file to be edited in change 1010
$ p4 update # Merges your code with changes from others

Now to submit my change

$ p4 submit -c 1010

Code has been checked into the Mother Repo, and I am done.

Thanks!

A big thanks to G Weiss and Matt Attaway.