Introduction to Branching in Perforce
by Robert Cowham, Perforce Consulting Partner
 
This web page gives an introduction to Perforce branching mechanisms
and explains some aspects that may not be obvious at first sight
(well they weren't to me anyway!).
 
Perforce's basic mechanism, Inter-File Branching is described on their web page. The main feature is
that branches of files are indicated by changing one or more elements
of the depot pathname (or location in the Perforce repository), and
this change is done by creating a virtual copy of the file using the
integrate command.
Examples of this are:
//depot/main/jam/jam.c
and
//depot/r1.0/jam/jam.c
or
//depot/main/jam/...
and
//depot/r1.0/jam/...
for complete trees of files.
The component of the depot path that has been modified is "main" and
"r1.0" respectively. In this example, we deduce ("elementary my dear
Watson") that the version of jam.c in r1.0 is related to a specific
version of the same file in main, and indeed that the r1.0 version
was released as part of Release 1.0 for the Jam product.
This brings up a key point - you
can branch a file from anywhere in the repository to anywhere else.
Perforce is clever - it will keep track of what is related to what
however complex that relationship. But to keep our lives simpler we
need to come up with appropriate conventions so that we can easily
"see" the relationships when we are browsing the repository (the KISS principle). Like most computer programs
Perforce is stupid enough to do exactly what we tell it to do as
opposed to what we meant it to do.
 
There are some words that Perforce uses somewhat (!) ambiguously (most notably
using the word "client" when "workspace" is meant), and "branch"
is one of them. This means any one of:
- a codeline (most likely meaning when used as a noun)
- a branch view specification (as in the entity created by "p4 branch" command - also a noun) - these are talked about below
- when used as a verb ("to branch") it means to use the "p4 integrate" command to create a new codeline (or branch!) of one or more files
Usually it is fairly obvious what is meant once you are comfortable
with the 3 alternatives, and to test your understanding I will use
them interchangeably below...
 
Noddy has some code sitting in //depot/main/jam/... which he wants to
branch into a release codeline for maintenance purposes. During the
creation of his new branch the files in //depot/main/jam/... are the
"source" files and the "target" files are somewhere else in the
repository (//depot/r1.0/jam/... in this instance).
So he does the following:
- Use "p4 client" and checks that his client workspace view mapping
includes the "source" and "target" of his intended branch.
- Runs "p4 integrate <source files> <target files>"
- Runs "p4 submit" to submit changes to the repository after which
point they become visible to other people.
E.g.
1. p4 client shows:
View:
//depot/main/jam/... //client/main/...
so he changes this to:
View:
//depot/main/jam/... //client/main/...
//depot/r1.0/jam/... //client/r1.0/...
There is a gotcha in this example - what happens if your mapping originally had //client/... on the right hand side (no "main"). Well remember that if you change the mapping and do a "p4 sync" Perforce will delete all the old files and move them down one level to underneath "main". Make sure you do not have any files opened for editing or similar when you do this.
2. He runs the integrate command which actually does most of the work:
p4 integrate //depot/main/jam/... //depot/r1.0/jam/...
Note that this also copies all the files into his client workspace.
3. He submits his changes and the new branch is visible in the repository to everyone.
p4 submit
 
Remember that when you branch a set of files, although it appears
that Perforce is copying all the files, (e.g. there are 1,000 files
in //depot/main/... and it appears as if there are now another 1,000
files in //depot/r1.0/..., giving 2,000 in total), that the newly
branched files are just virtual
copies. Perforce has duplicated the metadata in its database
to say that all the //depot/r1.0/... files now exist, but they are
just pointers to specific version of the real files in
//depot/main/....
Behind the scenes, the //depot/main/... files actually have RCS
format archives (for text files) to store all the details about the
contents of each revision (binary files are normally stored as a
compressed version of each revision - see "p4 help filetypes" for
more information). The files in //depot/r1.0/... only acquire their
own archive file on the server when they are modified (p4 edit and
then submit). Thus for typical situations where you branch 1,000
files and yet change less than 100, you only get less than 100 new
archive files on the server.
 
Branch specs are created using the p4
branch command.
The key thing to remember about them is that they are only a shorthand - creating a branch spec
does not branch files from its source to its target. Files are
actually branched when you use a branch spec with the integrate
command - it's the integrate command which does the work (not the
branch command).
Branch specs are particularly useful when you have multi-line views -
they save lots of typing, getting things wrong, forgetting about
things etc.
Remember that you can always delete branch specs and yet the work
that was done with them (using the integrate command) remains done,
even after the branch spec has been deleted (they are similar to
client workspace specs in this regard). I recommend that people do
delete the branch specs when they are no longer needed because if
they aren't there, people can't accidentally use the wrong ones -
it's always wise to remove temptation from your users...
 
Branch specs have a direction (source -> target). You can use the
branch spec and reverse the direction with the -r flag (see
below).
One thing lots of people do is to create a branch spec for a release branch such as:
Branch: r1.0
View:
//depot/main/jam/... //depot/r1.0/jam/...
They then normally only make bug fixes to the r1.0 branch and propagate them back to main and almost never in the reverse direction. This means that they always need to use the -r flag:
p4 integrate -r -b r1.0
Why not create the branch spec the "wrong" way round for its first usage (to create the branch):
View:
//depot/r1.0/jam/... //depot/main/jam/...
and then you will not need to use the -r flag in most subsequent uses because you are always going from r1.0 back to main.
 
It is generally a good idea to have at least one component of the
depot pathname as your "branch indicator". In the examples above the
"main" or "r1.0" components were the indicator.
Sometimes people rush in and add a whole set of files to the depot
without thinking about branching in future. For example adding source
files to //depot/jam/... instead of //depot/jam/main/... (or
similar). If you do this then you may have problems in the future
when it comes to creating new branches for these files - what should
the naming convention be?
 
So at this point we have covered some of the basics of the details of
branching. The thing we haven't touched on is some of the alternative
depot structures that are possible and why one might be better than
another (in some situations at least).
Standard Release Branches - Indicator first
As already covered above, there are some very simple and yet
effective structures for basic release purposes. E.g.
//depot/main/jam/...
is branched to:
//depot/r1.0/jam/...
//depot/r1.1/jam/...
This is very straight forward and easy to understand. One potential
drawback, is what happens if we have many releases - well we would
tend to clutter up the directory naming convention under //depot. An
option might be:
//depot/main/jam/...
is branched to:
//depot/release/r1.0/jam/...
//depot/release/r1.1/jam/...
Standard Release Branches - Indicator Second
If we have many products each of which we want to branch independently, then we could do something like:
//depot/productA/main/...
is branched to:
//depot/productA/r1.0/...
//depot/productA/r1.1/...
or:
//depot/productA/release/r1.0/...
//depot/productA/release/r1.1/...
as we prefer.
There is no particular difference, but it might make things easier if
we distinguish between the different products and don't mix them up
(as they might be when indicator came first).
Indicator first (again)
Another alternative which is useful when people have development branches (either team or personal) is:
//depot/main/productA/...
//depot/release/productA/r1.0/...
//depot/release/productA/r1.1/...
//depot/dev/personal/Fred/productA/...
//depot/dev/team/blue_team/productA/...
One advantage of this is that the first component of the path
indicates the basic use (main, release, etc.). The depths become
slightly more complex but this sort of things works rather well.
Notice the components in the /dev/personal and /dev/team to make sure
people understand what's going on and who "owns" the branch.
Weaving strands together
If we have a number of products each of which has associated
documents and tests etc, then one structure is (assume that all paths
are rooted under //depot):
| /main/src/ |
All source files |
| productA/... |
Sources for Product A |
| productB/... |
Sources for Product B |
| productC/... |
etc |
| /main/doc/ |
All documentation files |
| productA/... |
Docs for Product A |
| productB/... |
etc |
| /main/test/ |
All test files and documentation |
| productA/... |
Sources for Product A |
| productB/... |
etc |
Now we can branch "Product A" for release 1.0 as:
| /release |
All source files |
| /productA/1.0/ |
Release 1.0 of Product A |
| src/... |
Sources |
| doc/... |
Documentation |
| test/... |
Test |
The problem with the above is that when you branch either to create the release branch in the first place or to propagate changes back, you need multiple lines in your view - an excellent time to use branch view specs
in my mind.
As a general guideline, I prefer to have as simple a branch spec as possible to avoid "forgetting" things. I would try to go for one of the examples shown earlier. However, this is not always possible or indeed desirable.
 
If you have structured your repository thoughtfully, it is very
straight forward (as an administrator) to use the protect command to
create different protections for different branches. For example you
can allow all developers write access to the main line, but only a
small group to have write access to a particular release branch for
bug fixing. Indeed there might be older "frozen" releases which are
no longer being supported from which you could remove all write
access.
You can also write triggers which monitor submits to specific
branches and for example will not allow direct edits to files in that
branch but only integrates from other related branches.
(How to implement this is left as an exercise for the reader...)
 
Perforce offers a very flexible and powerful mechanism for branches
with which you can easily shoot yourself in the foot if you are not
careful. Think first, think again, plan, and only then start adding,
submitting and branching and remember to KISS and you will be OK (and
waste less time restructuring your depot later).
This page has shown a few examples and given a few guidelines as to
things to think about. The possibilities of course are endless and as
long as you have good reasons for doing things and you (and your
colleagues) can understand what is going on then branch away - have
fun!
I have made no attempt to look at some of the more complex aspects of branching:
- sibling branches
- the nitty gritty of propagating changes and partial integrations and the like
- integration histories
- scripting branch stuff
I can be contacted for questions and help in training and/or planning your
repository structure (
). Or you can sign up below for occasional hints and tips updates on Perforce.
 
For more examples of uses of branching and the principles involved I suggest you read:
Software Life-Cycle Modelling in Perforce - a good overview
Perforce branching
mechanisms
High-level Best Practices in Software Configuration Management - in
particular the description of the mainline branching model.
Please send feedback and comments on this page to
Footnotes
1) For the non-Brits amongst you, Noddy is a
character in Enid Blyton's children's books - whole generations of
us came across them. Q: Why do elephants have Big Ears? A: Because
Noddy wouldn't pay the ransom!
Back to the top
Contact us
© Vaccaperna Systems Ltd
|