Codelines, Branching and Streams
This chapter describes the tasks required to maintain groups of files in your depot. The following specific issues are addressed:
-
Depot directory structure and how to best organize your repository
-
Moving files and file changes among codeline and project directories
-
Identifying specific sets of files using either labels or changelists
To make codeline management easier, you can use streams, a Perforce feature that encapsulates numerous best practices and automations. This chapter includes a section describing how you use the Perforce command line client to manage streams. For basic information, refer to Introducing Perforce. For more details about using streams, see the P4V User's Guide, "Working with Streams".
This chapter focuses on maintaining a software code base, but many of the tasks are relevant to managing other groups of files, such as a web site. For advice about best practices, see the white papers on the Perforce web site.
Basic terminology
To enable you to understand the following sections, here are definitions of some relevant terms as they are used in Perforce.
Term |
Definition |
---|---|
branch |
(noun) A set of related files created by copying files, as opposed to adding files. A group of related files is often referred to as a codeline. (verb) To create a branch. |
integrate |
To create new files from existing files, preserving their ancestry (branching), or to propagate changes from one set of files to another (merging). |
merge |
The process of combining the contents of two conflicting file revisions into a single file, typically using a merge tool like P4Merge. |
resolve |
The process you use to reconcile the differences between two revisions of a file. You can choose to resolve conflicts by selecting a file to be submitted or by merging the contents of conflicting files. |
Organizing the depot
You can think of a depot as a top-level directory. Consider the following factors as you decide how to organize your depot:
-
Type of content: create depots or mainline directories according to the nature of your projects and their relationships (for example, applications with multiple components developed on separate schedules).
-
Release requirements: within a project, create branches for each release and integrate changes between branches to control the introduction of features and bug fixes.
-
Build management: use labels and changelists to control the file revisions that are built; use client specifications and views to ensure clean build areas.
A basic and logical way to organize the depot is to create one subdirectory (codeline) for each project. For example, if your company is working on Jam, you might devote one codeline to the release presently in development, another to already-released software, and perhaps one to your corporate web site. Your developers can modify their client views to map the files in their project, excluding other projects that are not of interest. For example, if Earl maintains the web site, his client view might look like this:
//depot/www/dev/... //earl-web-catalpa/www/development/... //depot/www/review/... //earl-web-catalpa/www/review/... //depot/www/live/... //earl-web-catalpa/www/live/...
And Gale, who's working on Jam, sets up her client view as:
//depot/dev/main/jam/... //gale-jam-oak/jam/...
You can organize according to projects or according to the purpose of a codeline. For example, to organize the depot according to projects, you can use a structure like the following:
//depot/project1/main/ //depot/project1/release 1.0/ //depot/project1/release 1.1/
Or, to organize the depot according to the purpose of each codeline, you can use a structure like the following:
//depot/main/project1/ //depot/main/project2/ //depot/release1.0/project1/ //depot/release1.0/project2/ //depot/release2.0/project1/ //depot/release2.0/project2/
Another approach is to create one depot for each project. Choose a structure that makes branching and integrating as simple as possible, so that the history of your activities makes sense to you.
Populating Codelines
If you are creating a codeline that has no history, use the p4 add command to add files to it, then use p4 copy to create branches. For example, to create the mainline structure shown in the previous section, perform the following steps:
-
Create a local folder your workspace for the mainline files; for example:
mkdir c:\p4clients\myworkspace\depot\main\
-
Copy the files for Project1 and Project2 to the newly created folder.
-
Add the files to the depot:
p4 add //depot/main/project1/... p4 add //depot/main/project2/... p4 submit
-
Create release branches:
p4 copy //depot/main/project1/... //depot/release1.0/project1/... p4 copy //depot/main/project2/... //depot/release1.0/project2/... p4 submit
Now you can use the p4 copy, p4 merge and p4 integrate commands to propagate changes between main and release branches. (You can also seed a codeline from another codeline using the p4 integrate command, if there is a historical relationship between the source and target that you need to preserve.)
A shortcut: p4 populate
If a target codeline is completely empty (no files present, not even deleted files), Perforce offers a command that automates the process of copying the files from an existing source codeline submitting the associated changelist.
For example, instead of populating a release1.0
branch with the
following two commands:
p4 copy //depot/main/project1/... //depot/release1.0/project1/... p4 submit
you can use the p4 populate command to populate the branch:
p4 populate //depot/main/project1/... //depot/release1.0/project1/...
Branching Codelines
Branching is a method of maintaining the relationship between sets of related files. Branches can evolve separately from their ancestors and descendants, and you can propagate (integrate) changes from one branch to another as desired. Perforce's Inter-File BranchingTM mechanism preserves the relationship between files and their ancestors while consuming minimal resources.
To create a branch, use the p4 integrate command. The p4 integrate command is also used to propagate changes between existing sets of files. For details about integrating changes, refer to Integrating changes.
When to branch
Create a branch when two sets of files have different submission policies or need to evolve separately. For example:
-
Problem : the development group wants to submit code to the depot whenever their code changes, regardless of whether it compiles, but the release engineers don't want code to be submitted until it's been debugged, verified, and approved.
Solution: create a release branch by branching the development codeline. When the development codeline is ready, it is integrated into the release codeline. Patches and bug fixes are made in the release code and integrated back into the development code.
-
Problem: a company is writing a driver for a new multiplatform printer. The UNIX device driver is done and they are beginning work on an OS X driver, using the UNIX code as their starting point.
Solution: create a OS X branch from the existing UNIX code. These two codelines can evolve separately. If bugs are found in one codeline, fixes can be integrated to the other.
One basic strategy is to develop code in //depot/main/
and create
branches for releases (for example, //depot/rel1.1/
). Make
release-specific bug fixes in the release branches and, if required, integrate them back
into the //depot/main/
codeline.
Creating branches
To create a branch, use the p4 integrate command. When you create a branch, Perforce records the relationships between the branched files and their ancestors.
You can create branches using file specifications or branch specifications. For simple branches, use file specifications. For branches that are based on complex sets of files or to ensure that you have a record of the way you defined the branch, use branch specifications. Branch specifications can also be used in subsequent integrations. Branch specifications also can serve as a record of codeline policy.
Using branch specifications
To map a set of files from source to target, you can create a branch
mapping and use it as an argument when you issue the p4
integrate command. To create a branch mapping, issue the p4 branch
branchname
command and specify the desired
mapping in the View:
field, with source files on the left and target
files on the right. Make sure that the target files and directories are in your client
view. Creating or altering a branch mapping has no effect on any files in the depot or
client workspace. The branch mapping merely maps source files to target files.
To use the branch mapping to create a branch, issue the p4 integrate -b
branchname
command; then use p4
submit to submit the target files to the depot.
Branch specifications can contain multiple mappings and exclusionary mappings, just
as client views can. For example, the following branch mapping branches the Jam
1.0
source code, excluding test scripts, from the main codeline.
Branch: jamgraph-1.0-dev2release View: //depot/dev/main/jamgraph/... //depot/release/jamgraph/1.0/... -//depot/dev/main/jamgraph/test/... //depot/release/jamgraph/1.0/test/... //depot/dev/main/bin/glut32.dll //depot/release/jamgraph/1.0/bin/glut32.dll
To create a branch using the preceding branch mapping, issue the following command:
p4 integrate -b jamgraph-1.0-dev2release
and use p4 submit to submit the changes.
To delete a branch mapping, issue the p4 branch -d
branchname
command. Deleting a branch mapping has
no effect on existing files or branches.
As with workspace views, if a filename or path in a branch view contains spaces, make sure to quote the path:
//depot/dev/main/jamgraph/... "//depot/release/Jamgraph 1.0/..."
Using file specifications
To branch using file specifications, issue the p4 integrate command, specifying the source files and target files. The target files must be in the client view. If the source files are not in your client view, specify them using depot syntax.
To create a branch using file specifications, perform the following steps:
-
Determine where you want the branch to reside in the depot and the client workspace. Add the corresponding mapping specification to your client view.
-
Issue the p4 integrate
source_files
target_files
command. -
Submit the changelist containing the branched files. The branch containing the target files is created in the depot.
Example 30. Creating a branch using a file specification
Version 2.2 of Jam has just been released, and work on version 3.0 is starting.
Version 2.2 must be branched to //depot/release/jam/2.2/...
for
maintenance.
Bruno uses p4 client to add the following mapping to his client view:
//depot/release/jam/2.2/... //bruno_ws/release/jam/2.2/...
He issues the following command to create the branch:
p4 integrate //depot/dev/main/jam/... //bruno_ws/release/jam/2.2/...
Finally, he issues the p4 submit command, which adds the newly branched files to the depot.
Integrating changes
After you create branches, you might need to propagate changes between them. For example, if you fix a bug in a release branch, you probably want to incorporate the fix back into your main codeline. To propagate selected changes between branched files, you use the p4 integrate, p4 merge, or p4 copy commands, as follows:
-
Issue the p4 integrate command to schedule the files for resolve. (In many cases, you can also use p4 merge or p4 copy.)
-
Issue the p4 resolve command to propagate changes from the source files to the target files.
To propagate individual changes, edit the merge file or use a merge program. The changes are made to the target files in the client workspace.
-
Submit the changelist containing the resolved files.
Example 31. Propagating changes between branched files
Bruno has fixed a bug in the release 2.2 branch of the Jam project and needs to integrate it back to the main codeline. From his home directory, Bruno types
p4 integrate //depot/release/jam/2.2/src/Jambase //depot/dev/main/jam/Jambase
and sees the following message:
//depot/dev/main/jam/Jambase#134 - integrate from //depot/release/jam/2.2/src/Jambase#9
The file has been scheduled for resolve. He types p4 resolve, and the standard merge dialog appears on his screen.
//depot/dev/main/jam/Jambase - merging
//depot/release/jam/2.2/src/Jambase#9
Diff chunks: 0 yours + 1 theirs + 0 both + 0 conflicting Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [at]:
He resolves the conflict. When he's done, the result file overwrites the file in his workspace. The changelist containing the file must be submitted to the depot.
To run the p4 integrate, p4 merge, or p4
copy commands, you must have Perforce write
permission on the
target files, and read
access on the source files. (See the
Perforce Server Administrator's Guide: Fundamentals for information on
Perforce permissions.)
By default, a file that has been newly created in a client workspace by p4 integrate cannot be edited before being submitted. To edit a newly integrated file before submission, resolve it, then issue the p4 edit command.
If the range of revisions being integrated includes deleted revisions (for example, a
file was deleted from the depot, then re-added), you can specify how deleted revisions are
integrated using the -Di
flag. For details, refer to the
P4
Command Reference.
Integrating using branch specifications
To integrate changes from one set of files and directories to another, you can use a branch mapping when you issue the p4 integrate command. The basic syntax of the integrate command when using a branch mapping is:
p4 integrate -b branchname
[tofiles
]
Target files must be mapped in both the branch view and the client view. The source
files need not be in the client view. If you omit the tofiles
argument, all the files in the branch are affected.
To reverse the direction of integration using a branch mapping, specify the
-r
flag. This flag enables you to integrate in either direction
between two branches without requiring you to create a branch mapping for each direction.
Example 32. Integrating changes to a single file in a branch
A feature has been added in the main Jam codeline and Bruno wants to propagate the feature to release 1.0 He types:
p4 integrate -b jamgraph-1.0-dev2release *.c
and sees:
//depot/release/jam/1.0/src/command.c#10 - integrate from //depot/dev/main/jam/command.c#97
The file has been scheduled for resolve. He types p4 resolve, and the standard merge dialog appears on his screen.
//depot/release/jam/1.0/src/command.c - merging //depot/dev/main/jam/command.c#97 Diff chunks: 0 yours + 1 theirs + 0 both + 0 conflicting Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [at]:
He resolves the conflict. When he's done, the result file overwrites the file in his branched client workspace; the file must then be submitted to the depot.
Integrating specific file revisions
By default, the integrate
command integrates all the revisions
following the last-integrated source revision into the target. To avoid having to manually
delete unwanted revisions from the merge file while editing, you can specify a range of
revisions to be integrated. If you are using p4 integrate, the
base
file is the closest common ancestor. If you are using
p4 merge, the base
file is the revision with
the most edits in common.
Example 33. Integrating specific file revisions
Bruno has made two bug fixes to //depot/dev/main/jam/scan.c
in
the main codeline, and Earl wants to integrate the change into the release 1.0 branch.
Although scan.c
has gone through 20 revisions since the fixes were
submitted, Earl knows that the bug fixes he wants were made to file revisions submitted in
changelist 30. He types:
p4 integrate -b jamgraph-1.0-dev2release //depot/release/jam/1.0/scan.c@30,@30
The target file (//depot/release/jam/1.0/scan.c
) is given as an
argument, but the file revisions are applied to the source. When Earl runs p4
resolve, only the revision of Bruno's file that was submitted in changelist 30
is scheduled for resolve. That is, Earl sees only the changes that Bruno made to
scan.c
in changelist 30. The file revision that was present in the
depot at changelist 29 is used as the base
file.
Reintegrating and reresolving files
After a revision of a source file has been integrated into a target, that revision is
skipped in subsequent integrations to the same target. To force the integration of
already-integrated files, specify the -f
flag when you issue the
p4 integrate command.
A target that has been resolved but not submitted can be resolved again by specifying
the -f
flag to p4 resolve. When you reresolve a
file, yours
is the new client file, the result of the original
resolve.
Integration reporting
The following reporting commands provide useful information about the status of files
being branched and integrated. Note the use of the preview flag (-n
)
for reporting purposes.
To display this information |
Use this command |
---|---|
Preview of the results of an integration |
p4 integrate -n [ |
Files that are scheduled for resolve |
p4 resolve -n [ |
Files that have been resolved but not yet submitted. |
p4 resolved |
List of branch specifications |
p4 branches |
The integration history of the specified files. |
p4 integrated |
The revision histories of the specified files, including the integration histories of files from which the specified files were branched. |
p4 filelog -i [ |
Streams
Perforce streams are "branches with brains," containers with which you compose a hierarchy that reflects your branching strategy. Streams are ideal for implementing the mainline branching model, in which volatile branches merge changes to keep up to date with their parents, then copy work to the parent when the work is stable enough to promote. Streams enable Perforce to generate views for associated workspaces, eliminating the need for you to update views manually to reflect changes to your branch structure.
For more information about streams, see the P4V User's Guide, "Working with Streams".
To work with streams, you perform the following steps:
-
Create a stream depot
-
Create and populate a mainline stream
-
Branch development and release streams
-
Merge and copy changes
To manage streams, you (mainly) use the following commands:
-
p4 stream
-
p4 streams
-
p4 merge
-
p4 copy
-
p4 resolve
-
p4 cstat
-
p4 istat
Additional commands that accept stream arguments are as follows:
-
p4 branch
-
p4 client
-
p4 clients
-
p4 diff2
-
p4 dirs
-
p4 integrate
-
p4 interchanges
For details about command syntax and flags, refer to the
P4
Command Reference or issue the p4 help
commandname
command. For a brief
overview, issue the p4 help streamintro command. The
following sections describe streams-related tasks in detail.
Stream Types
You assign stream types according to the stream's expected usage, stability and flow of change. Stream types are as follows:
Stream Type |
Stability |
Expected Flow of Change |
|
---|---|---|---|
Merge |
Copy |
||
|
Stable per your policy (for example, all code builds) |
from child (from release, or to development) |
to child (to release, or from development) |
|
N/A; used to filter streams |
N/A |
N/A |
|
Unstable |
from parent |
to parent |
|
Unstable |
from parent |
to parent |
|
Highly stable |
to parent |
from parent |
"Merging" means incorporating another stream's changes into your stream, and can require you to resolve conflicts. "Copy" propagates a duplicate of the source stream to the target. The following diagram shows a basic stream hierarchy: changes are merged down (to codelines of lesser stability) and copied up (to codelines of greater stability).

Stream types define default behavior for merging and copying, but you can override
these defaults by editing the toparent/notoparent
and
fromparent/nofromparent
options in the stream specification.
Stream Paths
Stream paths control the files and paths that compose a stream and define how those files are propagated. Except for the mainline, each stream inherits its structure from its parent stream. To modify the structure of the child, you specify paths as follows:
Type |
Sync? |
Submit? |
Integrate to/from Parent? |
Remarks |
---|---|---|---|---|
|
Y |
Y |
Y |
(Default) For files that are edited and propagated between parent and child streams. All files in a shared path are branched and, in general, shared paths are the least restricted. |
|
Y |
Y |
N |
For files that must not be propagated outside the stream but can be edited within it, such as binary build results. |
|
Y |
N |
N |
For components that must be physically present in the stream but are never changed. Example: third-party libraries. Import paths can reference a specific changelist to limit the imported
components to the revisions at that change or lower. Use the syntax
|
|
Y |
Y |
N |
Functions like an import path, in that it can reference an explicitly-defined depot path, but unlike a standard import path, you can submit changes to the files in an import+ path. |
|
N |
N |
N |
Files in the parent stream that must never be part of the child stream. |
In the following example, files in the src
path are not
submittable (and are imported from the parent stream's view), files in the
lib
path are not submittable (and are imported from an
explicitly-specified location in the depot), and files in the db
path
can be edited and submitted in the stream, but can never be copied to the parent:
Paths: share ... import src/... import lib/... //depot/lib3.0/... isolate db/...
The paths are used to generate the mappings for workspaces that are associated with the
stream. If the stream structure changes, the clients views of associated workspaces are
updated automatically and in fact cannot be altered manually. If the stream is
locked
, only the stream owner (or stream owners, if the
Owner:
of the stream is a group) can edit the stream specification.
Stream specification can also remap file locations (so that a file in specified depot location is synced to a different location in the workspace) and screen out files according to file type. For example, to ensure that object files and executables are not part of the stream, add the following entries to the stream specification:
Ignored: .o .exe
Creating streams depots
Streams reside in "stream" (as opposed to "local") depots. To create depots, you must
have super
privilege. To create a stream depot:
-
A Perforce superuser issues thep4 depot
depotname
command. The depot specification form is displayed. (Example: p4 depot projectX) -
Set the
Type:
field tostream
. -
Adjust other settings as desired and save the specification.
Note that you cannot modify the type of a depot after you create it.
Creating streams
All streams reside one (path) level below the depot that contains them. For example, for Project X, expect a set of streams with depot paths like the following:
-
//projectX/main
-
//projectX/dev-bruno
-
//projectX/release1.0
-
//projectX/release2.0
...and so on.
First, create the mainline stream, which resides at the center of your stream hierarchy. Typically, the mainline is a fairly stable receiving trunk, accepting development work from child streams and propagating the results to release streams where it can be stabilized and built for release without impeding ongoing development.
To create a mainline:
-
Issue the p4 stream command, specifying the depot followed by the stream name. (Example: p4 stream -t mainline //projectX/main). The stream specification form is displayed.
-
Change options as required, and save the specification.
-
To verify that your mainline stream has been created, issue the p4 streams command. (Example: p4 streams //projectX/...).
Next, populate the mainline with files.
Populating the mainline
There are two ways to populate the mainline stream:
-
Add files from the local filesystem, or
-
Branch files from another depot.
If you need to preserve file history, branch the source files to the mainline stream. If you have no requirement for preserving file history, simply add them. The following sections describe each approach.
First, create a workspace
Before you can work in a stream, you must create a workspace associated with the stream. When you associate a workspace with a stream, Perforce generates the workspace view based on the structure of the stream. You never need to edit the workspace view (and, in fact, cannot manually alter it). If the structure of the stream changes, Perforce will update the views of workspaces associated with the stream on an as-needed basis.
(Suggestion: When assigning names to stream-associated
workspaces, adopt a naming convention such as
user_depot_streamname
. For example,
bruno_projectX
. If you regularly switch between client workspaces
associated with different types of streams, you may also find it useful to append the
stream type, to your workspace name, for example, bruno_projectX_main
and bruno_projectX_dev
.)
To create a workspace for a stream:
-
Issue the p4 client command, using the
-S
flag to specify the name of the associated stream. (Example: p4 client -S //projectX/main bruno_projectX). -
The workspace specification form is displayed. (Note the
Stream:
field, which is present only for stream-associated workspaces.) -
Configure the workspace root directory and any other desired settings, and save the specification. You do not need to change the
View:
because this field will be maintained by Perforce. -
To verify that your workspace has been created, issue the p4 clients command (Example: p4 clients -S //projectX/main).
Now you can populate the mainline with files.
Adding files
If you do not need to preserve the historic connection between the source files and the files in the new mainline stream, simply add them. To add files to the mainline stream:
-
Create the workspace root directory if it does not exist. For example:
cd C:\Users\bruno\p4clients\ mkdir bruno_projectX_main
-
Copy the files and folders to the workspace root directory.
-
Change into the client workspace root directory, and use the p4 reconcile command to detect files not under Perforce control and open them for add:
p4 reconcile -a
To verify that the files are set up to be added correctly, issue the p4 opened command. To populate the stream, submit the changelist in which the files are open.
Branching from other depots
You can branch files from other stream depots, classic depots, or remote depots. If you populate the mainline by branching, Perforce preserves the connection between the revision history of the source and target files. Your workspace must be set to one associated with the target stream (example: p4 set P4CLIENT=bruno_projectX_main).
To populate the mainline by branching, issue the p4 copy command, specifying source and target. Example:
p4 copy -v //mysourcedepot/mainline/... //ProjectX/main/...
(In this example, the -v
flag improves performance by updating
the service without copying files to the workspace.) Perforce displays a series of "import
from" messages listing the source and target files, and opens the file in a pending
changelist. To preview the results of the operation without opening files, specify the
-n
flag. To undo an erroneous copy operation, issue the p4 revert
command; for example: p4 revert //ProjectX/main/...)
To verify that the files are set up to be added correctly, issue the p4 opened command. To populate the stream, p4 submit the changelist in which the files are open.
If you are populating an empty stream, you can simplify this process by using p4 populate. For example:
p4 populate //mysourcedepot/mainline/... //ProjectX/main/...
does the same thing as p4 copy -v followed by a p4 submit. If you are unsure of the results of p4 populate, use p4 populate -n, which previews the result of the command.
Populating child streams
After populating the mainline, you can branch files for development and for release. Development streams enable you to experiment without destabilizing the mainline, and release streams enable you to finalize existing features while working on new features in the mainline. For example, to create a development stream that is a clone of its mainline parent, issue the following command:
p4 stream -t development -P //projectX/main //projectX/dev
Perforce displays the stream specification with the type set to
development
. Save the specification. To populate the stream with the
files from the mainline, issue the following commands:
p4 client -s -S //projectX/dev bruno_projectX_dev p4 merge -S //projectX/dev -r p4 submit -d "Branching from mainline"
Or just use p4 populate:
p4 populate -d "From main" -S //projectX/dev -P //projectX/main -r //projectX/dev
Propagating changes
Streams enable you to isolate stable code from work in progress, and to work concurrently on various projects without impediment. Best practice is to periodically update less stable streams from streams that are more stable (by merging), then promote changes to the more stable stream (by copying). Merging and copying are streamlined forms of integration. In general, propagate change as follows:
-
For copying and branching, use p4 copy.
-
For merging, use p4 merge.
-
For edge cases not addressed by p4 merge or p4 copy, use p4 integrate.
The preceding guidelines apply both to streams and to classic depots.
Merging changes from a more-stable stream
To update a stream with changes from a more stable stream, issue the p4
merge -S source-stream
command, resolve as
required, and submit the resulting changelist. By default, you cannot copy changes to a
more stable stream until you have merged any incoming changes from the intended target.
This practice ensures that you do not inadvertently overwrite any of the contents of the
more stable stream.
Assuming changes have been checked into the mainline after you started working in the development stream (and assuming your workspace is set to a development stream), you can incorporate the changes into the development stream by issuing the following commands:
p4 merge -S //projectX/dev -r p4 resolve p4 submit -d "Merged latest changes"
Copying changes to a more-stable stream
After merging, your stream is up to date with its more stable parent or child. Assuming you've finalized the changes you want to make in the development stream, you can now promote its new content with no danger of overwriting work in the target stream. The "copy" operation simply propagates a duplicate of the source to the target, with no resolve required. For example, (and assuming your workspace is set to a mainline parent stream) to promote changes from the development stream to its parent mainline, issue the following commands:
p4 copy -S //projectX/dev p4 submit -d "Check my new feature in"
Propagating change across the stream hierarchy
You might need to propagate a specific change between two streams that do not have a
natural parent-child relationship, for example, to obtain an in-progress feature or bug
fix from a peer development stream. To merge from or copy to such a stream, you can
reparent your stream by editing its specification and setting the
Parent
field to the desired source or target. This practice is not
considered optimal but might be necessary.
Using task streams for sparse branching
Task streams are branches that work just like development streams, but they remain semi-private until branched back to the parent stream. Designed as lightweight branches, they are most effective when anticipated work in the branch will only affect a small number of files relative to the number of files in the branch.
Task streams do not require a parent stream. Because of this, even users who are not working in a stream depot can also take advantage of task streams. (The task stream must still reside in a stream depot, but your administrator can configure a stream depot as a dedicated holding place for task streams.)
Task streams are intended to be deleted or unloaded after use. Note that you cannot
re-use task stream names even after the stream has been deleted; most sites will adopt a
naming convention that is likely to be unique for each task, such as
user
-date
-jobnumber
.
Working within task streams is just like working in a development stream:
-
Create the task stream (in this example, as a child of a development stream)
p4 stream -t task -P //projectX/dev //Tasks/mybug123
-
Populate the stream
p4 populate -d "Fix bug 123" -S //Tasks/mybug123 -P //projectX/dev -r //Tasks/mybug123
-
Make changes to files in the stream
-
Merge down any required changes from the parent stream, resolving as necessary.
p4 merge -S //Tasks/mybug123 -r
-
Copy up the changes you made into the parent stream
p4 copy -S //Tasks/mybug123 -P //projectX/dev
-
Delete or unload the task stream.
p4 stream -d //Tasks/mybug123
(Alternatively, use p4 unload -s //Tasks/mybug123 to unload it.)
When in use, only the workspaces associated with the task stream can see all the files in the stream; the stream appears as a sparse branch to other workspaces, which see only those files and revisions that you changed within the task stream. Most other metadata for the task stream remains private.
Task streams can quickly accumulate in a depot until they are deleted or unloaded; to keep a project depot uncluttered by task streams, your Perforce administrator or project lead may choose to establish certain streams depots as dedicated holding areas for task streams. In this case, create your stream in the task streams depot as a child of a parent in the project depot.
Managing stream workspaces
This section discusses various approaches to managing your stream workspaces.
Using one workspace for multiple streams
Typically you define a workspace for each stream that you intend to work in. However, if your streams contain extremely large numbers of files (tens to hundreds of thousands, for example), this approach can require a time-consuming sync when you switch to working in a stream that has changed a lot since the last time you worked in it. If the structure of your streams is consistent and most files are identical, you can avoid this problem by reassociating your workspace with the stream you are switching to instead of using different workspaces for both streams. After you change the stream with which the workspace is associated, sync to obtain any files that differ.
To change the stream associated with a workspace, issue the following command:
p4 client -s -S //streamdepot
/
streamname
Narrowing the scope of workspaces with virtual streams
For large projects, even consistently-organized streams may not sufficiently restrict
workspace views. In large organizations, there are often many groups who are concerned
with only a small subset of a project's files. In classic Perforce, these users would
manually restrict their client workspace's view to include only the desired subset.
Streams offers an alternative; use a virtual
stream as a filter:
For example, if ongoing development work is occurring in an
//Ace/dev
stream:
Stream: //Ace/dev Parent: //Ace/main Type: development Paths: share ...
Then a user who is working only with the documentation for the product (rather than
all of the assets associated with the project) could create a virtual stream that includes
only those files under //Ace/dev/docs/...
, as follows:
Stream: //Ace/devdocs Parent: //Ace/dev Type: virtual Paths: share docs/...
The user can then can switch his or her client workspace to the
devdocs
virtual stream with the following command:
p4 client -s -S //Ace/devdocs
When using the devdocs
workspace, the user's client workspace view
is automatically updated to include only the material in
//Ace/dev/docs/...
and any changes he or she makes in
//Ace/devdocs
are automatically propagated back to the original
//Ace/dev
codeline without the need to manually run p4
copy or p4 integrate.
Viewing a stream as of a specific changelist
The StreamAtChange
option in the workspace specification lets you
set a stream workspace to sync a stream using the stream's view as of a specific
changelist. This gives you the ability to see a "back-in-time" view of your stream. This
is helpful when you want to see what the stream view was at a particular point in time,
especially if your stream definition changes a lot. When you use the
StreamAtChange
option, you cannot submit changes to the files in the
stream, since your workspace files are not at the head revision.
To set a stream workspace to sync as of a specific changelist:
-
Open the stream's workspace specification form for editing:
p4 client -S //projectX/main bruno_projectX
-
Enter the changelist number in the
StreamAtChange
field in thep4 client
form.
For more information, see the P4 Command Reference, "p4 client".