June 1, 2010

p4 move -f: What It's For

Traceability

One of the highlights of the 2010.1 server release is the "p4 move -f" command, which "allows the user to force a move to a file already synced to the client workspace." From this brief description it's probably not obvious what a useful feature this is, but it has the potential to make working with moved (e.g. refactored) files quite a bit easier, and we've found a few initially unintended uses for it as well, which I'll discuss briefly here.One of the highlights of the 2010.1 server release is the "p4 move -f" command, which "allows the user to force a move to a file already synced to the client workspace." From this brief description it's probably not obvious what a useful feature this is, but it has the potential to make working with moved (e.g. refactored) files quite a bit easier, and we've found a few initially unintended uses for it as well, which I'll discuss briefly here.

Before going into use cases, though, I'll explain what it means to "move to a file already synced". Normally, the "p4 move" command opens a new copy of a file with a new name (very similar to branching it), and opens the original file for delete. To create a new file, there must be nothing there to start with (either in the workspace or at the head rev in the depot), so prior to 2010.1 you would always get an error when trying to move to an existing file.

With the new "move -f" command, you can specify a synced file as the target of a move operation. The file will be opened for "edit" (rather than "move/add") as your local file is moved into its place. In addition, a resolve will be scheduled against the synced revision of the target file, which will allow you to merge your local edits with the depot revision that you had synced.

Why might you want to do this? Well, the use case that motivated this feature was having a file open for edit that has been moved in the depot -- you can no longer submit your edit in place, because the head rev of the open file is now a "move/delete". What you probably want to do instead is resolve your edit against the file in its new location, and submit it there. With "move -f" you can now do this by syncing the new depot file and moving your edit into it. If the file has been moved and/or edited multiple times, you have the option of resolving against each revision incrementally by syncing to that revision before moving to it -- or you can just sync to the head rev of the most current file and move directly there.

Since this feature was implemented, we've noticed that its usefulness goes well beyond dealing with already-moved files. "Reparenting" an open edit into another branch is surprisingly easy with the "move -f" command. Since "move -f" lets you move your edit to any arbitrary file or revision, you can just move your edits from one branch to another, and do a resolve to merge your edits with whatever is in that branch. This can be a real lifesaver if (as I did a few weeks ago) you start working on a fix in your mainline, and then decide that it needs to go into your release branch instead. Previously you would have needed to save a copy of your work, revert it, open the files in the release branch, and copy your edits back in manually -- now you just "p4 move -f main/... rel/..." and all your edits go where you need them. (Remember, "p4 move" only operates on files that are already open, so only the files you had open get moved over -- handy!)

Since the end result of a "move -f" operation is a normal file opened for edit, it can be combined with other operations without any special effort or consideration. Another possible use case might be quickly moving a "shelf" from one branch to another -- unshelve, "move -f" to the new branch, resolve, and reshelve.

As part of an internal training I gave on the "move -f" command I illustrated some step-by-step examples of the resolving and reparenting use cases that give a nice clear picture of what exactly the new command is doing; for your viewing pleasure those examples are now available in PowerPoint format here. Now that this feature is generally available I'm very curious to see what other uses people start coming up with!