February 1, 2016

Helix DVCS – Switching like a Pro



By now you should be well versed in initializing, cloning and administrating local servers. We now come to a more interesting use case: local streams[1].

Since a local server is my own personal sandbox, I can create as many streams as I like without having to worry about permissions or triggers. Even better, the process is extremely easy. Not convinced? Let’s try it out. Create a new local server, change to its root directory, and then type 

 $>p4 switch

This command should return “main”, which is the name of the stream we are currently in. I use this command in my little command prompt script to give me a simple visual guide.


Creating a new stream, the easy way

Let's add some content in this stream first to demonstrate the point.

  $>echo"Some content">file1.txt
  $>p4 rec 
  $>p4 submit-d “Some files”

So far so good (I love the ‘p4 rec’ alias for ‘p4 reconcile’). Now we shall create a new stream. I use the following command:

  $> p4 switch –c feature.a

The command returns the name of the new stream I am now in (run ‘p4 switch’ again without arguments to confirm).

If you used streams with P4V before, you are probably used to this simple switching of streams already: you can simply drag-and-drop your workspace icon from a child to parent stream and back, and P4V will associate your workspace with the selected stream and update your workspace. This required a few calls to the Helix server under the covers. Now you can do the same thing from the command line with a single command.

Let’s make a few tests. We shall add a new file to this stream, submit it and switch again.

  $> echo “Some other content” > file2.txt
  $> p4 rec
  $> p4 submit –d “Some files”


Swapping between streams

Fine, time to switch back to main. Ready?

  $> p4 switch main 

No visual clue this time that we have switched streams (which is one of the reasons I changed my command prompt to tell me). We expect this stream to have only file (file1.txt) in it.So, try an ‘ls’ (or ‘dir’ on Windows) or ‘p4 files ...’. True enough, only one file here.

Running ‘p4 switch’ automatically syncs the workspace to the latest state of the current stream – and it does so efficiently by only updating those files that are different to the files already in the workspace. If the streams do not differ too much, this process will be extremely efficient.


Propagating changes

Now I want to propagate my files from the feature.a stream to the main stream. I use:

  $> p4 merge --from feature.a
  $> p4 resolve -as
  $> p4 submit -d “propagated from feature.a”

The first command merges my changes from the feature.a stream, after which I must resolve any conflicts. This is probably surprising for users of other DVCS systems, but keep in mind that Perforce Helix has a lot more options on how to deal with streams, including the ability to ignore files and/or changes in order to create variants. I’ll handle the different resolve options and their use cases in a different post. For now, the “-as” (for “accept safe”) option will do the job. Finally, I submit my changes to complete the merge operation.

Now that all my changes are back in my main stream, I might want to create another feature stream (with ‘p4 switch -c feature.b’, for example). This time, my newly created files and my merged files will automatically be branched as well – with a single command. So now you can create streams, switch between them, submit changes into different streams, and easily propagate changes from one stream to another—locally, with all the performance boost that entails.


Final observations

But what happens if I have uncommitted changes in my current stream when I switch? I don’t want to lose any of my changes, but I don’t want to be prevented from switching either. Fortunately, ‘p4 switch’ has another trick up its sleeve: Before switching, the command automatically runs a ‘p4 reconcile’. If there are any changes, these are also automatically shelved before the switch happens, and then reverted before the actual switch happens.

The effect is that any uncommitted changes in my original stream are gone from the new stream but safely stored on a shelf (temporary storage similar to stashing in git, for example). When I switch back, my original state is restored from said shelf, bringing all my changes back, but with one big difference: my changes are now in the local pending changelist. I suppose you could run ‘p4 revert -k ...’ to reset your state if you are a purist[2]

The other question I asked myself is this: ‘p4 switch’ is amazingly powerful and useful, so why can’t I use this command for my work against the master server as well? As it turns out, you can use ‘p4 switch’ against the master server, with two caveats.

       1.  You can switch only between streams, not between classical branches.

       2.  You cannot create new streams with ‘p4 switch –c’ on a shared master server.



With Helix DVCS, you can quickly and conveniently create, switch, and manage work between any numbers of streams, giving you all the local power you need to work the way you want. If you haven't tried it yet download it now an give it a spin.

Next time, I’ll talk about how to push your changes back to the master server.

Happy hacking! Sven Erik


[1] If you haven’t used streams yet, for the purpose of this post they are like branches. Streams come in different types such as mainline (trunk), development or release and there is a parent/child relationship between streams to simplify propagating changes.

[2] A purist would probably argue that when switching back to the original streams, the state of the files and pending changelists should be exactly as it was before, but I found that ‘p4 switch’ did for me what I probably should have done myself, and saved me from issuing a few more commands in the bargain.