Perforce uses inter-file branching (branching in pathspace) and the standard branching model is to branch ahead of time and branch all the files you need.
For example, you branch all the files //depot/main/jam/… to //depot/dev/robert/my-task/jam/… and then update the files independently. Thus if you have 100 files in the original project you get all 100 in the branch as well. Behind the scenes this is an efficient operation in that Perforce only updates its meta data to make the 100 “copied” files appear to be there – the server uses “links” between the copied files and the original ones (via entries in the metadata database) so it doesn’t duplicate what it doesn’t need to.
The ClearCase model would be to setup a config spec which states that if you change any files then they are branched behind the scenes. Thus if you only change 5 files on the branch, then only those files are actually branched.
I categorise the CC model as sparse branching and the Perforce model as inclusive branching. See conclusion for pros and cons of each approach.
Normal Perforce Branching Model
Branch: robert/my-task-inclusive View: //depot/main/jam/... //depot/dev/robert/my-task-inclusive/jam/...
We branch the files like so:
C:\work\robert-my-task>p4 integ -b robert/my-task-inclusive //depot/dev/robert/my-task-inclusive/Build-new.com#1 - branch/sync from //depot/main/jam/Build-new.com#1 //depot/dev/robert/my-task-inclusive/Build.com#1 - branch/sync from //depot/main/jam/Build.com#1,#9 etc... C:\work\robert-my-task>p4 submit
which “copies” the 100 or so files in Jam to the new branch.
Our client workspace to work on the branch is very simple:
Client: robert-ws-incl
View:
//depot/dev/robert/my-task-inclusive/jam/... //robert-ws-incl/jam/...
So now we can work on the files on the branch and integrate changes to and from main in the normal manner (see below for integrating back to main).
Sparse Branching in Perforce
A new Perforce server feature makes this easier than it used to be.
Let’s create a branch spec and in the branch spec we branch only the files we know we are going to change, in this case one file at a time in the view:
Branch: dev/robert/my-task-sparse View: //depot/main/jam/jam.c //depot/dev/robert/my-task-sparse/jam/jam.c //depot/main/jam/jam.h //depot/dev/robert/my-task-sparse/jam/jam.h
And use it:
C:\work\robert-my-task>p4 integ -b robert/my-task-sparse //depot/dev/robert/my-task-sparse/jam/jam.c#1 - branch/sync from //depot/main/jam/jam.c#1,#35 //depot/dev/robert/my-task-sparse/jam/jam.h#1 - branch/sync from //depot/main/jam/jam.h#1,#49
C:\work\robert-my-task>p4 submit
How do I most easily use the newly branched files?
Well I can create a client workspace like this:
Client: robert-ws-sparse
View:
//depot/main/jam/... //robert-ws-sparse/jam/...
+//depot/dev/robert/my-task-sparse/jam/... //robert-ws-sparse/jam/...
Note that when we sync this, the following happens:
C:\work\robert-my-task-sparse>p4 sync //depot/main/jam/Build-new.com#1 - added as c:\work\robert-my-task-sparse\jam\Build-new.com //depot/main/jam/Build.com#9 - added as c:\work\robert-my-task-sparse\jam\Build.com //depot/main/jam/headers.h#2 - added as c:\work\robert-my-task-sparse\jam\headers.h //depot/dev/robert/my-task-sparse/jam/jam.c#1 - added as c:\work\robert-my-task-sparse\jam\jam.c //depot/dev/robert/my-task-sparse/jam/jam.h#1 - added as c:\work\robert-my-task-sparse\jam\jam.h //depot/main/jam/Jam.html#2 - added as c:\work\robert-my-task-sparse\jam\Jam.html etc...
Note that we get the branched copies of jam.c and jam.h and the normal copies of everything else. Thus we can work happily (though it might look a little strange in the p4win/p4v depot view). This uses the feature of “+” mappings which became official with 2005.1 of the server (they were undoc’ed for a while before that). From “p4 help views”:
A mapping line that begins with a + overlays the later mapping on the earlier one: if files match both the earlier and later mappings, then the file matching the later mapping is used. Overlay mappings are only allowed on client views, and make it possible to map multiple server directories to the same client directory.
Branching More Files
If we want to add a new file to the sparse branch then it is a little fiddly. The steps are:
- Add an appropriate mapping to the branch spec view
- Use “p4 integrate” and the modified branch spec to branch the file (and submit it)
- Re-sync our client workspace which will automatically bring in the newly branched file rather than the mainline version.
Integrating Changes Back to the Mainline
Note that for both of these models we can integrate our changes back to the mainline with a very simple client workspace:
Client: robert-ws-main
View:
//depot/main/jam/... //robert-ws-main/jam/...
This is because to integrate we only need the target of the integrate to be mapped in our client workspace so we can integrate from either the sparse or the inclusive version.
Finding Changed Files on an Inclusive Branch
It is actually rather easy in most cases to find the files that have changed on the branch (one of the sticking points for many people), even if you branched everything in the first place. The recipe is:
- find the changelist which created the branch (e.g. N)
- list all files on the branch from changelist N+1 to the head.
C:\bruno_ws>p4 changes //depot/dev/robert/jam/... Change 724 on 2006/10/19 by bruno@bruno_ws 'Some more stuff ' Change 723 on 2006/10/19 by bruno@bruno_ws 'Another change ' Change 720 on 2006/10/17 by bruno@bruno_ws 'Dev change ' Change 719 on 2006/10/17 by bruno@bruno_ws 'new brach ' C:\bruno_ws>p4 files //depot/dev/robert/jam/...@720,#head //depot/dev/robert/jam/Build.com#2 - edit change 720 (text) //depot/dev/robert/jam/Build.mpw#2 - edit change 720 (text) //depot/dev/robert/jam/command.c#2 - edit change 720 (text) //depot/dev/robert/jam/jam.c#2 - edit change 723 (text) //depot/dev/robert/jam/jam.h#2 - edit change 723 (text) //depot/dev/robert/jam/scan.c#2 - edit change 724 (text)
You can get slightly cleverer than the above if you are dealing with large numbers of changelists (e.g. pipe to tail, or look for changes to #1 of files). While this is command line stuff (and not easy in P4V for example), it can be very simply scripted and made available as a custom tool.
Doing Branching Within a Single Workspace/Environment
One time when I would certainly think more seriously about using the sparse model is when you wish to do some branching and yet you only have a single workspace/environment to test in. Now this is not a good situation to be in (and you should try very hard to get out of it), but I have seen it where for example people were doing database 4GL development and only had one database to develop and test in, and the costs to set up another environment appeared prohibitive.
In such a situation, you can use sparse branching and by changing your client workspace view (I usually cut and paste lines between the view and the description to save retyping), re-sync your workspace to either include the sparse branch or not. This is fiddly and error prone, but possibly useful in such situations.
Choosing Which Model
The disadvantages of the sparse model are the extra effort required to get new files onto the branch, and some extra server performance overhead in usage. The other problem is that you can’t use the sparse branch in its own right – a workspace must know the “base” branch to use together with the sparsely branched files. This might seem easy to do in the short term, but over time can become harder to communicate and there is more room for confusion. Inclusively branched files are just there and the whole branch can be used at any time in a standalone manner. Together with the recent advances in common ancestor detection, it is not difficult to propagate changes in a flexible manner.
The disadvantage of the Perforce model are:
- You have to branch ahead of time – it is fiddly to suddenly decide in the midst of making a change that you want to move this change to a separate branch (I will discuss options for this in a later article).
- It can be a little more messy to see what has really changed on the branch since all the files are branched and you have to check which ones have actually been changed (this is actually quite easy - see recipe).
As we have seen above, a disadvantage for the sparse model is that it is fiddly to add new files to the sparsely branched set.
Thus I think that the inclusive branching model is easier for most people. It is also the way Perforce was designed to work, and thus the way in which people have the most experience, so you will be in good company. It is often a recipe for making life hard when you start applying the thinking of another tool. One of the worst examples I saw of this is in using labels – a customer had 85,000 labels and counting – a huge mess (it wasn’t just labels, but labels of labels – impossible easily to tell which labels a file was in due to the composition). They got there by applying PVCS thinking to Perforce, instead of understanding and applying branching as it was designed to do. You have been warned!!
However, I am sure that there are situations where a branch of only a few files out of a largeish number is required and it is very useful to be able to see that only half a dozen say have been branched.
You pays yer money and makes yer choice (and bears the consequences)!



