Perforce Public Knowledge Base - "Cherry Picking" Integrations
Perforce Software logo
Reset Search



"Cherry Picking" Integrations

« Go Back



By default, the p4 integrate command attempts to integrate (merge) all previously unintegrated changelists between two given source and target codelines (streams). However, it is possible to select and integrate a single changelist from within a range of unintegrated changelists. Integrating a single changelist from a range of unintegrated changelists is often referred to as "cherry picking". Below is a simple example of a "cherry picked" integration and a discussion of its repercussions.


Cherry picking integration is a method to precisely propagate content from one codeline or stream to another. By specifying a single changelist from a range of candidate changelists, the p4 integrate command operates on a smaller, more easily understandable content change (delta).

When you cherry pick integrations, you explicitly avoid merging other unintegrated changelists. What should happen with those other unintegrated changelists? By default, those unintegrated changelists keep showing up as candidates for integration until they are dealt with in some manner ("resolved" in Perforce parlance). If you perform cherry picking integrations, you should also likely perform "bookkeeping" integrations. See below for details on bookkeeping integrations.

Cherry picking integrations can also affect how the "base" file is chosen for future integrations. When you perform a "cherry pick", the base file chosen is often different than the base file that would normally be chosen if you integrated the full default range of unintegrated revisions.

Cherry picking integrations can also affect integration reporting. Specifically, the output of p4 interchanges can report changes where cherry picked integrations are involved.


Below is a screenshot from the P4V Revision Graph tool showing a cherry picked integration of a single revision.  Note the square bracket is only above revision 3 in //depot/code/cherry/foo and not extending to other revisions. This shows that only the cherry picked change in revision 3 is propagated to revision 2 of //depot/code/cherry/bar.


P4V Example
  1. Create a new branch, cherry1

    From the Workspace tab, right-click New Folder, cherry1.
  2. Create a new file, file1.txt,  in this newly created folder

    Set the file contents as "Change A".  The file should be saved into the location seen in the drop down line under the P4V icons.  Name the file file1.txt. If you edit files using Windows notepad, make sure the bottommost line ends with a carriage return.
  3. Add file1.txt to Perforce

    In P4V, click View, Refresh.  Find file1.txt and right-click "Mark for Add".   Select View, Pending Changes, and right-click default and choose submit.  Enter a changelist description "Adding file1.txt" and submit this file.
  4. Create another new branch cherry2 from branch cherry1

    Right-click cherry1, Merge/Integrate, Merge method: Specify source and target files, Choose target  files/folders and change "cherry1" to "cherry2".  Click Preview to see if file1.txt will be integrated.  Close the Preview and click Merge.  From View, Pending Changelists, find the changelist holding file1.txt and right-click Submit.  Click Submit.  Now we have two branches, cherry1 and  cherry2 both with file1.txt in each branch.
  5. Submit a change to file1.txt that we do not want to propagate

    Right-click Check Out on file1.txt in branch cherry1.  Choose the default changelist or changelist of your choice. Double-click file1.txt and add a new line with the content "Change B".  Save and exit, choose View, Pending Changlists, right-click Submit, fill out the changelist description with "Update file1.txt", and Submit.  Note that we now have revision 2 of file1.txt in branch cherry1.
  6. Submit a change to file1.txt that we do want to propagate

    Right-click Check Out on file1.txt in branch cherry1.  Choose the default changelist or changelist of your choice. Double-click file1.txt and add a new line with the content "Change C" press enter to end the file with a carriage return / line feed.  Save and exit, choose View, Pending Changelists, right-click Submit, fill out the changelist description with "Update file1.txt again", and Submit.  Now we have revision 3 of file1.txt in branch cherry1.  Click View, Submitted Changelists and note the changelist number referencing "Update file1.txt again".  We want to propagate this changelist number.
  7. Perform a cherry pick integration

    Right-click folder cherry1 and choose Merge/Integrate.  On Choose target files/folders, change cherry1 to cherry2.  Choose Options and click the Filter tab.  On filter method, select "Revision range and files/folders".   On Revisions to merge, choose the dropdown of "Revisions equal to" because we just want to propagate just one changelist.  Choose the dropdown "Changelist" and browse to the desired "Update file1.txt again" changelist.  Click Preview and note that only Revision 3 of file1.txt will be propagated.  Close this preview window.  Click Merge, and note the target file in cherry2 has a branch arrow and question mark on its icon.
  8. Resolve as needed

    From View, Pending Changelists, right-click the changelist number and choose Resolve Files.  Click "Run Merge Tool" and note that the merge seen in the bottom pane will contain the desired changelist with Change C and will not contain the undesired changelist that contains Change B.  Click File, Save, File, Exit, and click Yes when prompted to replace file1.txt with the merged result.
  9. Submit

    This is your chance to make sure the integration is as you expected.  Click View, Pending Changelists and right-click the changelist with file1.txt in branch cherry2.  Double-click this file to double-check that it merged correctly.  Right-click the changelist and choose Submit if you are satisfied with the merge; otherwise, right-click Revert Files to undo the integration.  A successful cherry pick will contain the changelist with Change C but will not integrate the changelist with Change B.

    You can integrate the changelist with Change B later. Or if you do not want Perforce to ever integrate the changelist with Change B, resolve the changelist with Change B using "Accept Target" to ignore Change B and leave the target file unchanged.
Command Line Example

A similar example can be performed from the command line client.  If you use Windows, notepad files must end the file with a line feed and carriage return and you wil also want to run "p4 set P4MERGE=p4merge":
echo Change A > foo
p4 add foo
p4 submit -d "Add foo" foo

p4 integ foo bar
p4 submit -d "Branch foo" bar

p4 edit foo
echo Change B >> foo
p4 submit -d "Update foo" foo

p4 edit foo
echo Change C >> foo
p4 submit -d "Update foo again" foo

p4 integ foo#3,#3 bar
p4 resolve -o


Running the merge tool at this point will show you the results of the automatic merge, in which "Change C" is preserved and "Change B" is not:


This behavior is produced by the last integration command: p4 integ foo#3,#3 bar. By specifying only a single revision as the source revision range (#3,#3), only the "Change C" delta in foo#3 is applied to bar#2. Without specifying a single revision, the default behavior of the integrate command is to merge both "Change B" (foo#2) and "Change C" (foo#3).

The source revision that is not integrated (foo#2) remains a candidate for future integrations. If you do not need the unintegrated content delta from foo#2 in bar, then it is appropriate to do a so-called "bookkeeping" integration. A bookkeeping integration entails integrating changes that you do not want -- and then resolving them with p4 resolve and selecting "accept yours" to ignore the content of the source revision. For example:
p4 integ foo#2,#2 bar
p4 resolve -ay
p4 submit -d "Explicitly ignoring foo#2,#2" bar
If, instead, you edit foo again, you wind up with 2 unintegrated revisions: foo#2 and foo#4. If you now run p4 interchanges, you get, surprisingly, all 3 revisions listed as unintegrated. For example:
p4 interchanges foo bar
Change 3 on 2012/08/07 by fthompson@ws 'foo'
Change 4 on 2012/08/07 by fthompson@ws 'foo'
Change 7 on 2012/08/07 by fthompson@ws 'foo'
If you preview integrating foo to bar, all 3 revisions are included in the integration range:
p4 integ -n foo bar
//depot/bar#2 - integrate from //depot/foo#2,#4 using base //depot/bar#2
But if you instead try to cherry-pick foo#3 again, you see that it is still accounted for:
p4 integ foo#3,3 bar 
foo#3,3 - all revision(s) already integrated.



Related Links



Was this article helpful?



Please tell us how we can make this article more useful.

Characters Remaining: 255