Streams
This chapter describes concepts and procedures related to streams.
Introduction
Note
Be sure to read the “Basic Concepts” chapter of Introducing Helix before reading this chapter.
Streams are like branches, with additional intelligence built in. They provide clues of where and how to do branching and merging. They guide merging and branching actions that support both stability and innovation by encouraging the "`merge down, copy up'" best practice. In addition, using streams eliminates a lot of the work needed to define branches, to create workspaces, and to manage integrations.
Custom branching gives you finer grained control but you lose the convenience of built-in control over the flow of change and automatic workspace updating.
When you create a stream, you specify its type, information about the files it is associated with, its relationship to other streams, and how files are to be treated for branching and merging. The system uses the information you provide to encourage merging best practices and to track parallel development.
The stream type tells the system how stable the stream is relative to other streams. The stream’s path info tells the system a number of things; including which files to populate the workspace with, which files child streams are allowed to branch, and, if necessary, which changelist to lock the files at. Parent labeling specifies how the stream relates to other streams in the system, helping to determine how change flows through the system.
Streams are ideal for implementing the mainline branching model, in which less stable streams merge changes to keep up to date with their parents, then copy work to the parent when the work is stable enough to promote. In addition, streams enable the system to generate views for associated workspaces, eliminating the need for you to update views manually to reflect changes to your stream structure.
Stream workflow
This section walks you through the initial workflow for using streams.
-
Create a stream depot.
A stream depot contains one or more streams. Typically, a tech lead or administrator creates the stream depot. The syntax to create a stream depot is described in Create a stream depot. Stream depots are discussed in further detail in Stream depots.
-
Create a mainline stream.
A mainline stream 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 the work can be can be stabilized and built for release without impeding ongoing development. Typically, a tech lead or administrator creates a mainline stream. The syntax to create a mainline stream is described in Create a mainline stream.
When you create a stream, the server creates the stream’s corresponding stream specification (spec), which defines the stream’s characteristics. The stream spec is examined in detail in The stream specification. You fine-tune the stream spec at the time you create a workspace, when the server prompts you to edit the stream spec. You can also update the stream’s characteristics as needed, as described in Updating streams.
-
Create a workspace and bind it to the stream.
To do any work in a stream you need a workspace. The syntax to create a workspace and bind it to a stream is discussed in Create a workspace. For background information on workspaces, see Stream workspaces.
-
Populate the mainline stream.
This step adds files to the mainline stream created earlier. Typically, a tech lead or administrator populates a mainline stream. Once you’ve populated a mainline stream, you can use standard server commands to modify and submit files. For details on how to populate a mainline stream, see Populate a mainline stream.
-
Populate child streams.
This step adds stream(s) that are children of the mainline stream. Typically, an individual contributor, such as a developer, creates and populates child streams. Once you’ve populated a child stream, you can use standard server commands to modify and submit files. For details on how to populate child streams, see Populate child streams.
-
Make changes to files in one or more streams.
These changes will be propagated in the next step.
-
Propagate changes between streams.
This step merges or copies files between different streams. For example, you may merge changes from a mainline stream into a child development stream. Typically, an individual contributor, such as a developer, propagates changes between streams. For details on how to propagate changes between streams, see Propagate changes.
Stream procedures
This section provides instructions on how to perform common stream-related procedures. For conceptual information on streams, see Key streams concepts.
As summarized in Stream workflow, to work with streams, you perform the following steps:
- Create a stream depot.
- Create a mainline stream.
- Create a workspace and bind it to the stream
- Populate the mainline stream.
- Populate child streams.
- Make changes to files in one or more streams
- Propagate changes between streams.
Create a stream depot
To create a depot, you must have super privilege. To create a stream depot:
- Issue the
p4 depot depotname
command. The depot specification form is displayed. - 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.
Create a mainline stream
To create a mainline stream:
-
Issue the
p4 stream
, command, specifying the depot followed by the stream name.For example:
$ p4 stream -t mainline //projectX/main
The stream specification form is displayed.
- Change options in the spec to assign the stream the desired characteristics and save the spec.
-
To verify that your mainline stream has been created, issue the
p4 streams
command.For example:
$ p4 streams //projectX/...
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, Helix 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, Helix updates the views of workspaces associated with the stream on an as-needed basis.
Tip
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
option to specify the name of the associated stream.For 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 is maintained by the server. -
Verify that your workspace has been created using
p4 clients
.For example:
$ p4 clients -S //projectX/main
Now you can populate the mainline with files, as described in the next step.
Populate a mainline stream
There are two ways to populate a mainline stream:
- Add files from the local filesystem
- 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 sections that follow describe each approach.
Add 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:
C:\bruno_ws> cd C:\Users\bruno\p4clients 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 Helix control and open them for add.C:\Users\bruno\p4clients> cd bruno_projectX_main C:\Users\bruno\p4clients\bruno_projectX_main> p4 add ...
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.
Branch from other depots
You can branch files from other stream depots, classic depots, or remote depots
into a stream. If you populate the mainline by branching, Helix 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
option performs the copy on the server without syncing
the newly-created files to the workspace. This can be a significant time-saver
if there are many files being copied; you can then sync only the files you
intend to work with from the new location.
p4d
displays a series of “import from” messages listing the source and
target files, and opens the file(s) in a pending changelist. To preview the results
of the operation without opening files, specify the -n
option. To undo an
erroneous copy operation, issue the p4 revert
command; for example:
$ p4 revert //ProjectX/main/...
Helix displays the stream specification with the type set to development. Save the specification and exit the editor to create the stream. To populate the stream with the files from the mainline, issue the following commands:
- 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.
Populate child streams
After populating the mainline, you can branch files for development and for release. 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
Helix 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 populate -d "From main" -S //projectX/dev -r
$ p4 sync
Propagate 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
orp4 populate
. - For merging, use
p4 merge
. - For edge cases not addressed by
p4 merge
orp4 copy
, usep4 integrate
.
The preceding guidelines apply both to streams and to classic depots.
Comparing changes between streams
Using the p4 interchanges
command, you can compare changes between streams
to look for outstanding merges. Suppose you have a mainline stream
//stream/main
and its child, a development stream, //stream/dev
. The
following command tells you which changes exist in //stream/dev
but not in
its parent stream:
$ p4 interchanges -S //stream/dev
The following command tells you which changes exist in the parent of
//stream/dev
but not in //stream/dev
:
$ p4 interchanges -S -r //stream/dev
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
$ 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 --from //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 re-parent 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. Alternatively, you can use the -P
option with the p4 merge
command to do a one-off integration between
streams.
Key streams concepts
This section provides further information on key streams concepts, including:
- The stream specification
- Updating streams
- Stream types
- Stream paths
- Stream workspaces
- Stream depots
The stream specification
A stream spec names a path in a stream depot to be treated as a stream. A spec
defines the stream’s location, its type, its parent stream, the files in its
view, and other configurable behaviors. It is created when you create a stream
with the p4 stream
command. You can update the spec’s entries — as described in
Updating streams — to change the stream’s characteristics.
The following is a sample stream spec:
$ p4 stream -o //stream/child_of_main
# A Perforce Stream Specification.
#
# Use *'p4 help stream'* to see more about stream specifications and command.
Stream: //stream/child_of_main
Update: 2015/02/06 10:57:04
Access: 2015/02/06 10:57:04
Owner: jschaffer
Name: //stream/child_of_main (created by switch command)
Parent: //stream/main
Type: development
Options: allsubmit unlocked toparent fromparent mergeany
Description:
Our primary development stream for the project.
Paths:
share ...
import boost/... //3rd_party/boost/1.53.0/artifacts/original/...
import boost/lib/linux26x86_64/... //3rd_party/boost/1.53.0/artifacts/original/lib/linuxx86_64/gcc44libc212/...
import boost/lib/linux26x86/... //3rd_party/boost/1.53.0/artifacts/original/lib/linuxx86/gcc44libc212/...
import protobuf/... //3rd_party/protobuf/2.4.1/artifacts/patch-1/...
import gtest/... //3rd_party/gtest/1.7.0/artifacts/original/...
import icu/... //3rd_party/icu/53.1/artifacts/original/...
import p4-bin/lib.ntx64/vs11/p4api_vs2012_dyn.zip //builds/p15.1/p4-bin/bin.ntx64/p4api_vs2012_dyn.zip
import p4/... //depot/p15.1/p4/...
exclude p4/Jamrules
exclude p4/lbr/...
exclude p4/server/...
Remapped:
p4/doc/... p4/relnotes/...
Ignored:
.../~tmp.txt
The following table describes the stream spec in more detail:
Entry | Meaning |
---|---|
|
The Error in stream specification. Stream Check with your administrator to determine the permitted stream depth. |
|
The date the stream specification was last changed. |
|
The date the specification was originally created. |
|
The user or group who has specific and unique permissions to access to this stream. |
|
An alternate name of the stream, for use in display outputs. Defaults to the streamname portion of the stream path. |
|
The parent of this stream. Can be |
|
Type of stream provides clues for commands run between stream and parent. The
five types include |
|
A short description of the stream (optional). |
|
Stream Options: |
|
Identify paths in the stream and how they are to be generated in resulting
workspace views of this stream. Path types are
NoteFiles don’t actually have to be branched to appear in a stream. Instead, they can be imported from the parent stream or from other streams in the system. |
|
Remap a stream path in the resulting workspace view. |
|
Ignore a stream path in the resulting workspace view. Note that Perforce
recommends that you use |
More on options
The following table summarizes the meaning of each of the options available in the stream spec:
Option | Meaning |
---|---|
|
All users can submit changes to the stream. |
|
Only the stream owner can submit changes to the stream. |
|
The stream spec cannot be deleted and only the stream owner can modify it. |
|
All users can edit or delete the stream spec. |
|
Merges from the stream to its parent are expected. |
|
Merges from the stream to the parent are not expected. |
|
Merges to the stream from the parent are expected. |
|
Merges to the stream from the parent are not expected. |
|
Enforces the best practice of merge down, copy up. |
|
Allows you to merge the stream’s content both up and down. |
Updating streams
As part of maintaining your version control application, you will likely update streams over time, by changing any of the fields listed above, to do such things as:
-
modify the paths the stream consumes when the stream proves to be too narrow or too wide, in order to:
- change the version of an included library by modifying the target of an
import
path - change the scope of a path to widen or narrow the scope included
- change the version of an included library by modifying the target of an
- Change restrictions on who can submit to the stream
To do this, you modify stream specifications directly via the p4 stream
command, automatically and immediately updating all workspace views derived from
that stream.
Making changes to a stream spec and associated files atomically
Alternatively, you can isolate edits to the stream spec to the editing client prior to making them available to other clients as part of an atomic changelist submission. This works just as edits to files do: they are made locally on a single client and then submitted to make them available to other clients.
This functionality has a couple of important benefits:
- You can stage a stream spec in your workspace and test it before submitting it.
- You can submit the spec atomically in a changelist along with a set of files. Since the stream structure dictates the workspace view, this means that when users sync, they obtain the new view and the new files together.
You open and submit changes to the stream spec using the following three commands:
p4 stream edit
puts the client’s current stream spec into theopened
state, isolating any edits made to fields that affect view generation. While the spec is open, those fields are marked with the comment#open
to indicate that they are open and isolated to your client. Changes made to these fields affect your workspace view normally, but other clients are not affected.p4 stream resolve
resolves changes that have been submitted to the stream spec by other users since you opened it. You may not submit changes to the stream spec until newer changes have been resolved.p4 stream revert
reverts any pending changes made to the open spec, returning your client to the latest submitted version of the stream.
For details on all three of these commands, see the p4 stream
page in the
P4 Command Reference.
By default, the open stream spec is included along with files that are
shelved or submitted in a changelist. Conversely, when unshelving a change that
contains an open stream spec, the current stream is opened and the shelved
version becomes the opened version. If the stream is already open when
attempting to unshelve, a warning is generated and the unshelve operation
aborts. The stream may be omitted from any of these operations by using the -Af
flag to specify that only files should be acted upon.
See the p4 submit
, p4 shelve
, and p4 unshelve
commands in the
P4 Command Reference for details.
Stream types
You assign stream types according to the stream’s expected usage, stability and flow of change:
- Development streams are used for code that changes frequently; they they enable you to experiment without destabilizing the mainline stream.
- Mainline streams contain code that changes somewhat frequently, but is more stable than code in development streams.
- Release streams contain the most stable code, as this is the code closest to being released. Release streams enable you to finalize existing features while working on new features in the mainline.
There is also a virtual stream type and a task stream type. See Task streams and Virtual streams, respectively.
On a scale of stability, a development stream is considered less stable than its mainline stream parent, while a release stream is considered more stable than its mainline stream parent. Change is expected to flow down by merging, and up by copying. This “merge down, copy up” practice assures that merging is done only when necessary, and always in the more forgiving of the two streams involved.
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 streams of lesser stability) and copied up (to streams of greater stability):

The following table summarizes these qualities of stream types:
Stream Type | Stability | 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 |
Task streams
Task streams are lightweight short-lived streams used for bug fixing or new features that only modify a small subset of the stream data. Since branched (copied) files are tracked in a set of shadow tables that are later removed, repository metadata is kept to a minimum when using this type of stream and server performance is optimized.
They are branches that work just like development streams, but task streams 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 are intended to be deleted or unloaded after use. Because you cannot re-use task stream names even after the stream has been deleted, most sites 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 -r
- Make changes to files in the stream and submit the changes.
-
Merge down any required changes from the parent stream, resolving as necessary.
$ p4 merge
-
Copy up the changes you made into the parent stream.
$ p4 copy --from //Tasks/mybug123
-
Delete or unload the task stream.
$ p4 stream -d //Tasks/mybug123
Alternatively, use:
$ p4 unload -s //Tasks/mybug123
to unload it. Use unload if you think you might to work on the task stream again.
Only 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 Helix 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.
Task streams are unique in that they can live in different depots from their children or parents. However, the best practice is to have them reside in the same depot as their children or parents.
Virtual streams
Virtual streams can be used to create alternative views of real streams. Virtual streams differ from other stream types in that a virtual stream is not a separate set of files, but instead a filtered view of its parent stream. A virtual stream can have child streams, and its child streams inherit its views.
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 the 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 files that must be physically present in the stream but are never changed.
Example: third-party libraries. Import paths can reference a specific
changelist (or a label that aliases a changelist) to limit the imported files
to the revisions at that change or lower. Use the syntax @changelist#, as
in: |
|
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 |
|
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 workspace views 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:
field of the
stream is set to 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
Stream paths and inheritance between parents and children
Child streams inherit folder paths and behavioral rules from their parents. When we talk about inheritance between parents and children, it helps to think in the following terms:
-
Permissiveness: what actions (submit, sync, etcetera) are permitted on a path?
Path types are inherited from parent streams, and you cannot override the effects of the path types assigned by parent streams. In other words, child streams are always as permissive or less permissive than their parents, but never more permissive. For example, if a parent stream defines a path as
isolate
, its child streams cannot redefine the path asshare
to enable integrations. -
Inclusiveness: what paths are included in the stream?
Since children cannot, by definition, be more inclusive than their parents, you cannot include a folder path in a child that is not also included in its parent. This means, for example, that you cannot add an
isolate
path to a child if the folders in that path are not also included in the parent.In the example in the table below, the incorrectly defined
Dev
stream, which is a child ofMain
, contains anisolate
path that does not work, because it includes folders that are not included in the parent. In order to isolate theconfig/
folder in theDev
stream, that folder has to be included as ashare
orisolate
path inMain
:Incorrect Correct Stream: //Acme/Main Parent: none Paths: share apps/... Paths: share tests/... Stream: //Acme/Dev Parent: //Acme/Main Paths: share apps/... share tests/... isolate config/...
Stream: //Acme/Main Parent: none Paths: share apps/... share tests/... share config/... Stream: //Acme/Dev Parent: //Acme/Main Paths: share apps/... share tests/... isolate config/...
Example 34. Simple share
Let’s start with a simple case: two streams, //Ace/main
and its child
//Ace/dev
.
Stream: //Ace/main Parent: none Paths: share ... Stream: //Ace/dev Parent: //Ace/main Paths: share ...
In this case, the entire stream path is shared. When you switch your workspace
to the //Ace/main
stream, the workspace view looks like this:
//Ace/main/... //your_ws/...
The workspace view maps the root of the //Ace/main
stream to your workspace.
When you you switch your workspace to the //Ace/dev
stream, the workspace view
is this:
//Ace/dev/... //your_ws/...
And the branch view for //Ace/dev/
looks like this:
//Ace/dev/... //Ace/main/...
In other words, the entire dev
stream can be synced to workspaces, and the
entire stream can be branched, merged, and copied.
Example 35. Share and import
Let’s look at an example where software components are housed in three separate
depots: //Acme
, //Red
, and //Tango
.
The Acme
mainline is configured like this:
Stream: //Acme/Main Parent: none Paths: share apps/... share tests/... import stuff/... //Red/R6.1/stuff/... import tools/... //Tango/tools/...
If you switch your workspace to the //Acme/Main
stream, this would be your
workspace view:
//Acme/Main/apps/... //your_ws/apps/... //Acme/Main/tests/... //your_ws/tests/... //Red/R6.1/stuff/... //your_ws/stuff/... //Tango/tools/... //your_ws/tools/...
The stream’s Paths
field lists folders relative to the root of the stream.
Those are the folders you get in your workspace, beneath your workspace root.
The shared folders are mapped to the //Acme/Main
path, and the imported paths
are mapped to their locations in the //Red
and //Tango
depots.
Example 36. Share, isolate, exclude, and import
Let’s say that your team doesn’t want to do actual development in the mainline. In this example, XProd feature team has a development stream of their own, defined like this:
Stream: //Acme/XProd Parent: //Acme/Main Paths: import ... isolate apps/bin/... share apps/xp/... exclude tests/...
Switching your workspace to the //Acme/XProd
stream gives you this view:
//Acme/Main/apps/... //your_ws/apps/... //Acme/XProd/apps/bin/... //your_ws/apps/bin/... //Acme/XProd/apps/xp/... //your_ws/apps/xp/... //Red/R6.1/stuff/... //your_ws/stuff/... //Tango/tools/... //your_ws/tools/... -//Acme/XProd/tests/... //your_ws/tests/...
Here we see workspace view inheritance at work. The contents of imported paths are mapped into your workspace. The shared and isolated paths are mapped to the child stream; these contain the files the XProd team is working on and will be submitting changes to. And the excluded path (marked with a minus sign in the view) doesn’t appear in the workspace at all.
Because the //Acme/XProd
stream has a parent, it has a branch mapping that can
be used by the copy and merge commands. That branch view consists of the
following, with just one path shared by the child and parent.
Note
You must use the Perforce Command Line Client to view stream branch views.
-//Acme/XProd/apps/... //Acme/Main/apps/... -//Acme/XProd/apps/bin/... //Acme/Main/apps/bin/... //Acme/XProd/apps/xp/... //Acme/Main/apps/xp/... -//Acme/XProd/stuff/... //Acme/Main/stuff/... -//Acme/XProd/tests/... //Acme/Main/tests/... -//Acme/XProd/tools/... //Acme/Main/tools/...
When you work in an //Acme/XProd
workspace, it feels as if you’re working in a
full branch of //Acme/Main
, but the actual branch is quite small.
Example 37. Child that shares all of the above parent
Let’s suppose that Lisa, for example, creates a child stream from
//Acme/XProd
. Her stream spec looks like this:
Stream: //Acme/LisaDev Parent: //Acme/XProd Paths: share ...
Lisa’s stream has the default view template. Given that Lisa’s entire stream path
is set to share
, you might expect that her entire workspace will be mapped to
her stream. But it is not, because inherited behaviors always take precedence;
sharing applies only to paths that are shared in the parent as well. A workspace
for Lisa’s stream, with its default view template, has this client view:
//Acme/Main/apps/... //your_ws/apps/... -//Acme/LisaDev/tests/... //your_ws/tests/... //Acme/LisaDev/apps/bin/... //your_ws/apps/bin/... //Acme/LisaDev/apps/xp/... //your_ws/apps/xp/... //Red/R6.1/stuff/... //your_ws/stuff/... //Tango/tools/... //your_ws/tools/...
A workspace in Lisa’s stream is the same as a workspace in the XProd stream,
with one exception: the paths available for submit are rooted in
//Acme/LisaDev
. This makes sense; if you work in Lisa’s stream, you expect to
submit changes to her stream. By contrast, the branch view that maps the
//Acme/Dev
stream to its parent maps only the path that is designated as
shared in both streams:
-//Acme/Main/apps/... //XProd/apps/... -//Acme/LisaDev/tests/... //XProd/tests/... -//Acme/LisaDev/apps/bin/... //XProd/apps/bin/... //Acme/LisaDev/apps/xp/... //your_ws/apps/xp/... -//Red/R6.1/stuff/... //XProd/stuff/... -//Tango/tools/... //XProd/tools/...
The default template allows Lisa to branch her own versions of the paths her team is working on, and have a workspace with the identical view of non-branched files that she would have in the parent stream.
Stream workspaces
To submit files to a stream, you must use a workspace that is bound to that
stream; such a workspace is known as a stream workspace. A stream workspace is
bound to a stream by way of the Stream:
field in the workspace spec. The paths
listed in the stream spec determine which files appear in a workspace view.
With stream workspaces you don’t have to manually set up a workspace view;
instead the system automatically generates the workspace view from the Paths:
section of the stream spec. Thus, if you switch a workspace from one stream to
another, or if you modify a stream’s view template, all workspaces bound to the
stream update accordingly.
In order to submit changes to files in a stream, you must use a workspace bound to
or associated with that stream. Opening a file outside of your stream-generated view for
edit with p4 edit
gives a warning that the file cannot be submitted.
For example, suppose your stream spec contains the following two entries under
Paths:
:
Paths: import ... isolate apps/bin/... share apps/xp/... exclude tests/...
Switching your workspace to this stream gives you this workspace view:
//Acme/Main/apps/... //your_ws/apps/... //Acme/XProd/apps/bin/... //your_ws/apps/bin/... //Acme/XProd/apps/xp/... //your_ws/apps/xp/... //Red/R6.1/stuff/... //your_ws/stuff/... //Tango/tools/... //your_ws/tools/... -//Acme/XProd/tests/... //your_ws/tests/...
See Stream paths for more information on the relationship between paths listed in the stream spec and workspace (also known as client) views.
By default, p4 stream
edits the stream associated with your current
workspace. It throws an error if you’re not using a stream workspace.
Managing stream workspaces
This section discusses various approaches to managing your stream workspaces.
Using one workspace for multiple streams
When working with multiple streams, you have two choices:
- Switch one workspace between multiple streams; the workspace is appropriately populated whenever you switch from one stream to another. While this requires some extra processing, it is the right choice when you don’t need to work on different streams at the same time and you don’t want to have multiple streams on disk at the same time.
-
Establish a distinct workspace for each stream. This is the right choice if you want to move quickly between different streams or if you want to have multiple streams on disk at the same time.
Note that distinct workspaces must have distinct workspace roots — that is, distinct local folders.
To change the stream associated with a workspace, issue the following command:
$ p4 switch streamname
To get a workspace view and a set of files as of a specific changelist, issue the following command:
$ p4 switch stream
@change
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 Helix, these users would manually restrict their 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 workspace to the devdocs
virtual
stream with the following command:
$ p4 switch //Ace/devdocs
When using the devdocs
workspace, the user’s 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 made directly in the
original //Ace/dev
codeline without the need to manually run p4 copy
or
p4 merge
.
Viewing a stream as of a specific changelist
The StreamAtChange
option in the workspace specification lets you use the
version of the stream specified as of a particular changelist to generate a
workspace view. This is helpful when you want to see what the stream view was at
a particular point in time, especially if your stream spec changes a lot (for
example, if you frequently change what you’re importing or what you’re deciding
to share). When you use the StreamAtChange
option, you cannot submit changes
to the files in the stream, since your workspace view is not up to date.
To set a stream workspace to use the version of the stream specified as of a particular changelist, do the following:
-
Open the stream’s workspace specification form for editing.
$ p4 client
-
Use one of the following alternatives:
- Edit the form to set
StreamAtChange:
to the changelist you want to view the stream as of. Or, -
Issue this command:
$ p4 client -S //Ace/main@12546
- Edit the form to set
For more information, see the P4 Command Reference.
Alternatively, you can issue the following command to sync a stream using the stream’s view as of a specific changelist:
$ p4 switch [-r -v] stream
@change
This command both sets the StreamAtChange
value and syncs to the same change.
Stream depots
Streams are rooted in stream depots. A mainline and all of the streams related to it are rooted in the same stream depot. A server can host multiple stream depots. Although a stream depot can have multiple mainlines, one mainline per stream depot is recommended. Stream depots exist as separate namespaces from classic depots so that users don’t mix stream and non-stream content.