Using a Private Branch

This document explains how to use a Perforce private branch for Farrago development. A private branch allows you to check in code whenever you want without worrying about breaking someone else's build. Only when you integrate to a shared tree do your changes become visible to anyone else. This means you can save changes frequently (reducing the amount of code lost should your machine crash) and test experimental changes across multiple machines without having to copy files around.

Creating Your Branch

Before creating a private branch, you need to decide on the shared tree from which your private branch will sprout. The correct shared tree is wherever you have been checking out code already. The most common case would be //open/dev/..., which we'll use in the examples below.

Next, you need to decide where your branched files will live in the Perforce depot. Standard policy is to create your branch under //open/users/.... Never create your branch under a shared tree, otherwise everyone who maps that shared tree will accidentally map your private branch as well. So, if your Perforce user name is pmarlowe, you might use //open/users/pmarlowe/dev/... to branch from //open/dev/....

Your new branch also needs a name. A good name in this case would be dev_to_pmarlowe, which specifies the branch origin (dev), branched location (pmarlowe), and branching direction (later on it will become apparent why this naming convention is important).

To actually create the branch, issue a command like:

p4 branch dev_to_pmarlowe
Edit the Description field to give more details on the purpose of your branch, and define the branch view mapping:

        //open/dev/thirdparty/... //open/users/pmarlowe/dev/thirdparty/...
        //open/dev/saffron/... //open/users/pmarlowe/dev/saffron/...
        //open/dev/fennel/... //open/users/pmarlowe/dev/fennel/...
        //open/dev/farrago/... //open/users/pmarlowe/dev/farrago/...
Defining the branch view is pretty much like defining a client view, except that the right hand side references the depot rather than the client. It's a good idea to include everything you think you're going to need, because changing the branch definition later can lead to trouble. For example, don't try to economize on disk space by leaving out thirdparty and trying to share the local copy from another branch; getting this right and keeping it working as things change is more trouble than it's worth.

Request Access Rights

Unfortunately, you won't be able to use the branch you just created unless you have access rights to the branched location, which you probably don't. Send mail to the Farrago administrator, providing the name of the branch, and wait for a reply.

Perform Initial Integration

Once you have the required access rights, the next step is to edit your client view to add your branched location. So, you might end up with something like:

        //open/dev/thirdparty/... //pmarlowe.pi/dev/thirdparty/...
        //open/dev/saffron/... //pmarlowe.pi/dev/saffron/...
        //open/dev/fennel/... //pmarlowe.pi/dev/fennel/...
        //open/dev/farrago/... //pmarlowe.pi/dev/farrago/...
        //open/users/pmarlowe/dev/thirdparty/... //pmarlowe.pi/pmarlowe/thirdparty
        //open/users/pmarlowe/dev/saffron/... //pmarlowe.pi/pmarlowe/saffron
        //open/users/pmarlowe/dev/fennel/... //pmarlowe.pi/pmarlowe/fennel
        //open/users/pmarlowe/dev/farrago/... //pmarlowe.pi/pmarlowe/farrago
This would place your local pmarlowe directory as a sibling to your local dev directory. This structure is up to you to decide; something deeper becomes necessary when you have multiple private branches corresponding to multiple shared trees.

Now, before performing the initial integration (populating the private branch in the depot), sync all files which are to be branched so that you are branching from the latest version. In this example:

p4 sync //open/dev/...
will do the trick. Also, make sure you have no files open before starting the integration. This is very important, and is true for the other integrations described later on. Run p4 opened and make sure that the response is "File(s) not opened on this client." Mixing real changes with integrations will lead to much gnashing of teeth and tearing of hair.

Now, tell Perforce to do the integration:

p4 integrate -t -b dev_to_pmarlowe
The -t is redundant here but becomes important later, so get in the habit of including it whenever you invoke p4 integrate; otherwise you'll have nasty problems when file types change.

The p4 integrate command doesn't really do all of the work; it just tells Perforce what you're planning to do. To complete the branching in your client workspace:

p4 resolve -am
At this point, you should be able to build, run, and test under the local pmarlowe directory just created by p4 resolve. Once that looks good, check in (this won't affect anyone else):

p4 submit
The checkin comment should indicate Your private branch is now open for business.

Propagating Other Developers' Changes from the Shared Tree

Without a private branch, the first thing you would probably do before starting a new task would be to execute p4 sync to start from the latest code. With a private branch in place, there are a few extra steps:
  1. p4 sync as usual. Make sure you sync both the shared tree and your private branch location, otherwise you'll experience unpleasant anomalies later. And make sure you have no files open.
  2. p4 integrate -t -b dev_to_pmarlowe
  3. Run the above integrate command again to make sure it says nothing needs to be done. Sometimes during a big integrate real warnings will be buried in all the success messages. If you get a warning, use the warning text and p4 help resolve to try to figure out what you need to do.
  4. p4 resolve -am. If you have made changes in your private branch, they may conflict with changes coming in from the shared tree. In that case, use the normal conflict resolution process.
  5. Run resolve again to make sure it says nothing needs to be done.
  6. At this point, you may want to build and run tests in your private branch to make sure you aren't polluting your private branch with someone else's breakage. Make sure you are working in the correct local tree (a good idea is to set up multiple shell launchers in your desktop, one for each branch, and arrange for the shell window title to display the branch location). If tests fail, use p4 revert to undo the integration. If you trust the shared tree, you can skip this step.
  7. p4 submit to update your private branch with the integration before starting on your own changes or integrating subsequent changes from the shared tree (it's not a good idea to mix). This submit does not affect anyone else, so you should always do it sooner rather than later. A good convention for the checkin comment is integrate dev_to_pmarlowe@XXX where XXX is the change number you synced and integrated from.

Propagating Your Changes Back to the Shared Tree

OK, now you've done some development, submitted changes to your private branch, and are ready to publish those changes to the shared tree for everyone else to see. Before doing anything else, it's a good idea to do another propagate in the forward direction and merge the latest changes into your private branch (just as it's a good idea to sync and resolve before submit when working without a private branch). After that, the steps for the real checkin are almost the same as above:
  1. p4 sync. And make sure you have no files open.
  2. p4 integrate -t -r -b dev_to_pmarlowe. The -r tells Perforce to go in the reverse direction. Since the branch name was chosen to describe the forward direction, reverse integration will be from pmarlowe to dev, which is what we want.
  3. Run the above integrate command again to make sure it says nothing needs to be done.
  4. p4 resolve -am and resolve any conflicts. If you followed the advice above about doing another forward integration, there shouldn't be any unless some other doofus just checked in during this window.
  5. Run resolve again to make sure it says nothing needs to be done.
  6. At this point, you definitely want to build and run tests in the shared tree to make sure your changes have been properly merged (even if you didn't get any merge conflicts). If tests fail, the best approach is to debug and then p4 revert to back out of the integration before fixing the problem (in your private branch).
  7. Once all is well, p4 submit; this is the only real checkin from the perspective of other developers, so your checkin comment should probably summarize all of the changes made in your private branch (and maybe list the relevant change numbers).

More to Explore

Did all of the notes above scare you a bit? Good. Branching should never be undertaken lightly, even in a source-control system with excellent support for it such as Perforce. If you carefully adhere to the above procedures, you should have very few problems. However, if things get sticky, it's a good idea to make sure you understand the underlying concepts well before seeking a resolution. A good resource is the branching chapter from the official Perforce User's Guide. The links at the end have some more info on general branching theory. Also, if an integration should go haywire, remember that nothing is made permanent until p4 submit. So if you want to back out and restart the whole procedure, just use p4 revert and then p4 opened to make sure that all files have been successfully reverted.