Perforce Revision Control

Terence Parr

Introduction

Perforce is a simple yet extremely powerful revision control system (RCS), whose purpose is to manage multiple people working on the same set of files. An RCS tracks all changes to a file so you can back up to prior versions. It also acts as a versioned back up scheme.

Perforce uses a client-server architecture. You notify perforce when you want to add or edit files on your local disk and then, after doing your changes, you submit them to the central repository. At that time, another team member can sync his/her local disk to the updated repository. Programmers still work independently, but you share files via the central repository.

Importantly, this "submit" is done as a single transaction. That means that if the submit fails for lack of net connection in the middle of the submit, perforce will roll back the submit command. You can try again later without worrying about doubly submitting files.

Tasks

Get a file into the system

$ cd ~/depot/test
~/USF/depot/test $ ls
A.java    B.java    templates
~/USF/depot/test $ p4 add A.java
//depot/test/A.java#1 - opened for add
~/USF/depot/test $ p4 add *.java
//depot/test/A.java#1 - currently opened for add
//depot/test/B.java#1 - opened for add
~/USF/depot/test $ p4 add templates/*.st
//depot/test/templates/link.st#1 - opened for add
//depot/test/templates/page.st#1 - opened for add

At this point, you hvae 2 Java files and two template files in the change list. The depot won't commit these changes until you submit.

When you type p4 submit, an editor pops up with the submit description file like this:

# A Perforce Change Specification.
# ...
Change: new

Client: parrt.localhost

User:   parrt

Status: new

Description:
        add test files

Files:
        //depot/test/A.java     # add
        //depot/test/B.java     # add
        //depot/test/templates/link.st  # add
        //depot/test/templates/page.st  # add

You fill in the description and save/exit the file/editor. You'll see:

Change 6 created with 4 open file(s).
Submitting change 6.
Locking 4 files ...
add //depot/test/A.java#1
add //depot/test/B.java#1
add //depot/test/templates/link.st#1
add //depot/test/templates/page.st#1
Change 6 submitted.

Edit / submit file(s)

File A.java just has a comment let's say:

/** A */

If you want to edit A.java, say this:

~/USF/depot/test $ p4 edit A.java
//depot/test/A.java#1 - opened for edit

then edit A.java to be:

/** A */
public class A {
}

You can see what changes you've made since the last commited change:

~/USF/depot/test $ p4 diff A.java
==== //depot/test/A.java#1 - /Users/parrt/USF/depot/test/A.java ====
1a2,3
> public class A {
> }

To commit your changes, type this:

~/USF/depot/test $ p4 submit

You'll see an editor open with:

...
Description:
        <enter description here>

Files:
        //depot/test/A.java     # edit

After saving/exiting, you'll see:

Change 7 created with 1 open file(s).
Submitting change 7.
Locking 1 files ...
edit //depot/test/A.java#2
Change 7 submitted.

Get change history for a file

~/USF/depot/test $ p4 changes A.java
Change 7 on 2003/10/21 by parrt@parrt.localhost 'added code '
Change 6 on 2003/10/21 by parrt@parrt.localhost 'add test files '

Using p4 changes -u parrt A.java limits listed changes to only those done by parrt.

Delete a file

Deleting a file is like an edit and can be reverted before committing it.

~/USF/depot/test $ ls
A.java    B.java    templates
~/USF/depot/test $ p4 delete B.java
//depot/test/B.java#1 - opened for delete
~/USF/depot/test $ ls
A.java    templates
~/USF/depot/test $ p4 revert B.java
//depot/test/B.java#1 - was delete, reverted
~/USF/depot/test $ ls
A.java    B.java    templates

To commit, use p4 submit as always. You can always bring the file back later.

Rename or move a file

Copy to new file, add that file, delete old one. This is the simplest way.

~/USF/depot/test $ cp B.java C.java
~/USF/depot/test $ p4 add C.java
//depot/test/C.java#1 - opened for add
~/USF/depot/test $ p4 delete B.java
//depot/test/B.java#1 - opened for delete
~/USF/depot/test $ p4 submit
Change 8 created with 2 open file(s).
Submitting change 8.
Locking 2 files ...
delete //depot/test/B.java#2
add //depot/test/C.java#1
Change 8 submitted.
~/USF/depot/test $ ls
A.java    C.java    templates

Making sure your local disk is up-to-date

~/USF/depot/test $ p4 sync
File(s) up-to-date.

Going to another box though with a depot->client mapping, you'll see:

[parrt@nexus depot]$ p4 info
User name: parrt
Client name: parrt.nfs
Client host: nexus.cs.usfca.edu
Client root: /home/parrt/depot
...
[parrt@nexus depot]$ p4 sync
//depot/test/A.java#2 - added as /home/parrt/depot/test/A.java
//depot/test/C.java#1 - added as /home/parrt/depot/test/C.java
//depot/test/templates/link.st#1 - added as
/home/parrt/depot/test/templates/link.st
//depot/test/templates/page.st#1 - added as
/home/parrt/depot/test/templates/page.st

Cutting a release

You'll probably want to make a release for each 2 week project presentation so you know exactly what state your project was it at those stages. You'll use p4 label. See Labels.

File collisions

Please read Resolving File Conflicts.

Processes

Directory structure

Underneath your /home/user/depot directory team members may set up whatever they want as far as structure. I suggest something like this:

src
    webmail
        managers
            PersistenceManager.java
            UserManager.java
        pages
            PageDispatcher.java
            mail
                MessagePage.java
                MessageListPage.java
            misc
                LoginPage.java
        support
web
    images
        yourlogo.gif
        background.gif
    error.jsp
scripts
    backup.sh
    logprocessing.sh
lib
    templates
        page.st
        link.st
        pages
            home.page.st
            mail
                message.st
                summary.st
            misc
                login.st

If you currently have all your code under the /home/user/resin directory, I suggest strongly that you move it. The only code related to the server is webmail.PageDispatcher and you should move your code to a nice directory structure like the above. Resin only needs to see things in your CLASSPATH. You'll also need to set resin's document root to be /home/user/depot/web or something so your images and other web-related files can be seen.

When to submit to the depot

The central respository is the place where you store a mostly working version of your code as you both make changes. Without doing real development branches, you must be careful about what you submit. You can't just change any file you want and submit as it might not even compile with the rest of the code.

I suggest that, at minimum, you only submit code to the depot that compiles.

What if your partner has modified file B.java in a way that will break A.java, which you are modifying? You must pull the updated B.java onto your computer and make A and B work together before submitting. In other words, you should always do a p4 sync and try to compile before submitting. The sequence goes like this:

user x user y
p4 edit A.java p4 edit B.java
edits A.java edits B.java
still editing p4 sync (nothing from depot has changed)
still editing p4 submit B.java (B.java changes in depot)
p4 sync (pulls in new B.java) ...
javac *.java (compile errors; fixes A.java to suit B.java) ...
p4 submit A.java ...

After a submit, the code will always at least compile.

It would also be great if you tested your code before submitting so that your partner is not stuck solving your bugs and not doing his/her own work.

Command summary

command description
p4 help commands list all commands
p4 help command get help on command
p4 info Are my P4 parameters set properly? Is server up?
p4 add file Announce intention to add a file to the depot
p4 submit Submit all changes (add,edit,delete) to depot
p4 submit dir/... Submit all changes (add,edit,delete) to depot from dir on down
p4 sync Make my disk look like the depot (pulls in changes from your team members)
p4 sync dir/... Make my disk look like the depot from dir on down team members
p4 revert file Throw away changes you have made to that file
p4 changes file describe changes made to this file
p4 resolve -as if nothing conflicts, this "safe" resolve just works You will have to do "p4 resolve" after this to do conflicts that -as couldn't handle automatically.
p4 resolve find out what didn't resolve

Client Management

How perforces know what the depot<->local-disk mapping is

I have set up a user account in the perforce depot and a client for each user called user.nfs. The user is your user@cs.usfca.edu name. Your client looks like:

Client: <user>.nfs
Owner:  <user>
Root:   /home/<user>/depot/main
View:
        //depot/cs601/group<n>/main/... //<user>.nfs/...

which means that the groupN/main directory for cs601 in the central repository is mapped to your /home/user/depot/main directory. The reason for the main subdirectory will become clear when we discuss branching.

(by the way, that is the StringTemplate I used to generate all of your clients automatically <wink>.)

I have set up the protections as follows:

        write group group1 * //depot/cs601/group1/...
        write group group2 * //depot/cs601/group2/...
        write group group3 * //depot/cs601/group3/...
        write group group4 * //depot/cs601/group4/...
        write group group5 * //depot/cs601/group5/...
        write group group6 * //depot/cs601/group6/...
        write group group7 * //depot/cs601/group7/...
        write group group8 * //depot/cs601/group8/...
        write group group9 * //depot/cs601/group9/...
        write group group10 * //depot/cs601/group10/...
        write group group11 * //depot/cs601/group11/...
        write group group12 * //depot/cs601/group12/...
        write group group13 * //depot/cs601/group13/...

meaning for example, that group3 members only has access to //depot/cs601/group3 and below.

Please set your password by using p4 user command!

How perforce knows which depot to talk to

You must have file /home/user/depot/.p4 with the following info:

P4CLIENT=user.nfs
P4USER=user
P4PASSWD=
P4PORT=phantom:1666

For perforce to know to look in this "hidden" file (due to the prefix of a dot), you must have

export P4CONFIG='.p4'

in your .bash_profile or whatever.

With this set up, then you cannot accidentally add files outside of /home/user/depot/... directory subtree.