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.
$ 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.
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.
~/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.
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.
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
~/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
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.
Please read Resolving File Conflicts.
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.
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 | 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 |
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!
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.