We have a product that will be ported and released on HP and on Solaris. Should we branch //depot/main into //depot/variant-hp and //depot/variant-sol? And then should we branch off of those for each release? That seems like a lot of branches to maintain.
I suspect your platform-specific porting can be done in client workspaces mapped to //depot/main. In this day and age, we expect source code to be portable enough that a product can be built on any platform from the same codeline. However, your actual situation may require a branch, so read through the following scenarios and decide for yourself.
Let's say Ruth and Bob are working on fixing generic bugs, Harry is working on HP, and Susan is working on Solaris. A summary of their client specs might look like this:Client Root View ------ ---- ---- ruth-bugs /ruth_fs/bugfix //depot/main/... //ruth-bugs/... bob-bugs /bobsdisk/work //depot/main/... //bob-bugs/.... harry-hp /hp1/harry //depot/main/... //harry-hp/... susan-sol /work/solport //depot/main/... //susan-sol/...Each works in his/her own workspace. Before they check in changes from their workspaces, they will have to make sure their changes do not disrupt the build or cause regressions, because they're all checking changes into the same codeline, //depot/main. However, that should not be a problem for typical porting and bug fixing.
On the other hand, say Harry and Susan are both working on a complex internationalization retrofit of a stable product. Their code changes are likely to cause destabilization, and they need to check in their untested changes so they can share them with each other while they're implementing their retrofit. In this case you would need a separate codeline. Everything would be branched from the //depot/main codeline into //depot/i18n, for example, using this branch spec:Branch: i18n-retro View: //depot/main/... //depot/i18n/...and these commands:p4 integ -v -b i18n-retro p4 submit(The -v flag causes p4 to do the branching on the server, without involving the client workspace. Even though the //depot/i18n files still have to be mapped in your client view, they aren't copied to your workspace just to branch them in the depot. This is extremely efficient -- try it!)
Once the codeline is branched, Harry and Susan would set up their client views to work in the //depot/i18n codeline. Now you'd have clients mapped to two codeline branches:Client Root View ------ ---- ---- ruth-bugs /ruth_fs/bugfix //depot/main/... //ruth-bugs/... bob-bugs /bobsdisk/work //depot/main/... //bob-bugs/.... harry-i18n /local/i18n //depot/i18n/... //harry-i18n/... susan-retro /work/retro //depot/i18n/... //susan-retro/...When Harry checks in a change, Susan can pull his change into her workspace with p4 sync. However, when Ruth and Bob sync, their workspaces are unaffected by Harry's I18N-specific changes.
As Ruth and Bob fix bugs, however, Harry and Susan are going to need those fixes. So Harry, as the czar of the //depot/i18n codeline, periodically pulls the //depot/main changes into //depot/i18n with:p4 integ -b i18n-retrofit p4 resolve p4 submitAnytime Harry does this, Susan can then update her I18N workspace with the bug fixes using p4 sync.
Eventually Harry and Susan reach their goal of making the I18N product work. Now their changes need to be integrated into //depot/main. Ruth, as the czar of //depot/main, pulls changes from //depot/i18n with:p4 integ -r -b i18n-retrofit p4 resolve [builds product & runs regression tests] p4 submitSo now, the new release is ready. Let's say Ruth is in charge of the release. (It's good to have someone in charge.) Since development is likely to be ongoing in //depot/main, Ruth is going to branch //depot/main into //depot/r3. So here's what the branch spec looks like:Branch: r3 View: //depot/main/... //depot/r3/...She creates another client for herself so she can have a //depot/r3 workspace:Client: ruthr3 Root: /ruth_fs/r3 View: //depot/r3/... //ruthr3/...She branches the //depot/main codeline into //depot/r3 with these commands:p4 integ -v -b r3 p4 submitNow you have three codelines://depot/i18n +------------- / //depot/main -------+------+---------- \ //depot/r3 +----------Ruth and her staff build the Release 3 product from the //depot/r3 codeline on all platforms. They use dedicated release workspaces on each platform, and set up client specs for each one. E.g.:Client Root View ------ ---- ---- rel3-bsd /nfs1/rel3/bsd //depot/r3/... //rel3-bsd/... rel3-hp /nfs1/rel3/hp //depot/r3/... //rel3-hp/... rel3-sol /nfs1/rel3/sol //depot/r3/... //rel3-sol/...Note that in this example all three of these workspaces are sitting on the same filesystem, /nfs1. If your source code and build system are set up in a way that allows you to build product for more than one platform from the same source code directory tree, you could even use a single workspace, e.g.,Client Root View ------ ---- ---- rel3 /nfs1/rel3 //depot/r3/... //rel3/...As long as the mount looks like "/nfs1" from every platform, you can use the same client spec regardless of which platform you're on.
Now, what happens if a bug is found in the I18N retrofit? Let's say Release 3 has been out the door for some time, everything hunky-dory, but now there's this critical I18N bug that has to be fixed for Release 3 customers.
With Inter-File Branching, you could fix the bug in any of the three codelines, and integrate the fix from that codeline into the other two. However, the best place to fix it is in //depot/r3. Why?
- If you fix it in //depot/i18n, you have to integrate the fix from there into //depot/main, and from there into //depot/r3. That's one extra integrate-resolve step.
- If you fix it in //depot/main, and there has been subsequent new development there, you are applying the fix to code that has evolved beyond Release 3. Perforce does facilitate integrating individual deltas, but it's extra work for you during the 'resolve' process.
So, Harry is going to fix the I18N bug, and he does it in a new client workspace he sets up for //depot/r3. His client spec looks something like:Client: harry-r3 Root: /local/r3 View: //depot/r3/... //harry-r3/...Harry uses these commands to handle the bug fix:setenv P4CLIENT harry-r3 p4 sync # Gets files into his new r3 workspace ...... # Does some debugging p4 open foo.c bar.c # Makes problem files writeable ...... # Edits, rebuilds, & tests p4 submit # Checks in bug fix to //depot/r3So now Ruth can rebuild the release after doing a p4 sync in her //depot/r3 workspace.
She can also integrate all Release 3 bug fixes into the //depot/main with:setenv P4CLIENT ruth-bugs p4 sync p4 integ -r -b r3 p4 resolve p4 submitIf bug fixes are going into //depot/r3, and new development is going into //depot/main, what is //depot/i18n good for? Nothing, now. Once all changes have been integrated from //depot/i18n into //depot/main, //depot/i18n can be retired.
Using a client spec that has a view of //depot/main, you can check to see if there are any changes that still need integrating with:p4 integ -n -r -b i18n-retroAnd you can either leave the //depot/i18n files in place in the depot, or you can tidy up by deleting the files and the branch spec:p4 delete //depot/i18n/... p4 submit p4 branch -d i18n-retro(You need to use a client spec that has a view of //depot/i18n to delete the files.)
You won't save much space on the server by deleting the files (because branched files are only virtual copies unless modified), but by deleting them you are leaving an obvious signpost that they are no longer needed.
If you've read this far, I congratulate you. I hope I've come within at least shouting distance of the answer to your questions...