Perforce Public Knowledge Base - Making An Exact Copy of a Branch
× PRODUCTS SOLUTIONS CUSTOMERS LEARN SUPPORT
Downloads Company Partners Careers Contact Free Trials
Menu Search
Perforce
Reset Search
 

 

Article

Making An Exact Copy of a Branch

« Go Back

Information

 
Problem

How do I make a set of target files (in one branch/stream) identical to a set of source files (in another branch/stream) ?
 

Solution

Note: For server versions 2010.2 or later the p4 copy or the p4 copy -f command can be used to make one branch an exact copy of another.  Use the -f flag to copy deleted files.

In addition to copying source files to the target, all files in the target which do not exist in the source are deleted. The result is an exact copy of the source to the target.

Here is how to make an exact copy of a branch without the p4 copy command.

EXAMPLE HISTORY

The 'trunk' branch has three files that do not exist in the 'rel5.1' branch. Also, four files are common to both branches.

$ p4 files //dev/branch/rel5.1/...
//dev/branch/rel5.1/baz51a.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51b.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51c.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51dev.java#4 - add change 18 (text)

$ p4 files //dev/branch/trunk/...
//dev/branch/trunk/bar65a.java#2 - integrate change 20 (text)
//dev/branch/trunk/bar65b.java#2 - integrate change 20 (text)
//dev/branch/trunk/bar65c.java#2 - integrate change 20 (text)
//dev/branch/trunk/baz51a.java#2 - integrate change 19 (text)
//dev/branch/trunk/baz51b.java#1 - branch change 16 (text)
//dev/branch/trunk/baz51c.java#1 - branch change 16 (text)
//dev/branch/trunk/baz51dev.java#2 - delete change 25 (text)

Before the copy the file content of file baz51a.java is different in each branch.

$ cat ./rel5.1/baz51a.java 
class HelloWorld 
 public static void main(String[] args
 
 System.out.println("Hello 5.1 Development!")
 
 

$ cat ./trunk/baz51a.java 
class HelloWorld 
 public static void main(String[] args
 
 System.out.println("Hello World!")
 
 

EXAMPLE STEPS

When integrating from 'rel5.1' to 'trunk', you want the files in 'trunk' to all be deleted - regardless if the file existed before or not in 'rel5.1', thus making an exact copy of the source branch, 'rel5.1'.

  1. Open files for delete in 'trunk' that are not in the 'rel5.1' source branch. Also open files for delete which differ in content.
    $ p4 -Ztag diff2 -q //dev/branch/rel5.1/... //dev/branch/trunk/... | grep "depotFile2" | cut -d " " -f3 | p4 -x - delete
    //dev/branch/trunk/bar65a.java#2 - opened for delete
    //dev/branch/trunk/bar65b.java#2 - opened for delete
    //dev/branch/trunk/bar65c.java#2 - opened for delete
    //dev/branch/trunk/baz51a.java#2 - opened for delete
    
    $ p4 submit -d "Deleting any files not in rel5.1 branch and files which differ in content."
    Submitting change 26.
    Locking 4 files ...
    delete //dev/branch/trunk/bar65a.java#3
    delete //dev/branch/trunk/bar65b.java#3
    delete //dev/branch/trunk/bar65c.java#3
    delete //dev/branch/trunk/baz51a.java#3
    Change 26 submitted.
    
  2. Run p4 integrate from the source to the target using the -f flag.
    $ p4 integrate -f //dev/branch/rel5.1/... //dev/branch/trunk/...
    //dev/branch/trunk/baz51a.java#3 - branch/sync from //dev/branch/rel5.1/baz51a.java#1,#3
    //dev/branch/trunk/baz51b.java#1 - integrate from //dev/branch/rel5.1/baz51b.java#1,#3
    //dev/branch/trunk/baz51c.java#1 - integrate from //dev/branch/rel5.1/baz51c.java#1,#3
    //dev/branch/trunk/baz51dev.java#2 - branch/sync from //dev/branch/rel5.1/baz51dev.java#4
    
  3. Run p4 resolve using the -at flag.
    /home/myclient/dev/branch/trunk/baz51b.java - vs //dev/branch/rel5.1/baz51b.java#1,#3
    /home/myclient/dev/branch/trunk/baz.java - vs //dev/branch/rel5.1/baz51c.java#1,#3
    //adminwksp/dev/branch/trunk/baz51b.java - copy from //dev/branch/rel5.1/baz51b.java
    //adminwksp/dev/branch/trunk/baz51c.java - copy from //dev/branch/rel5.1/baz51c.java
    

    If you want, run the p4 resolved command to view the resolved files.

    $ p4 resolved
    /home/myclient/dev/branch/trunk/baz51a.java - branch from //dev/branch/rel5.1/baz51a.java#1,#3
    /home/myclient/dev/branch/trunk/baz51b.java - copy from //dev/branch/rel5.1/baz51b.java#1,#3
    /home/myclient/dev/branch/trunk/baz51c.java - copy from //dev/branch/rel5.1/baz51c.java#1,#3
    /home/myclient/dev/branch/trunk/baz51dev.java - branch from //dev/branch/rel5.1/baz51dev.java#4
    
  4. Submit the integrated changes.
    $ p4 submit -d "Making an exact copy of rel5.1 to trunk"
    Submitting change 27.
    Locking 4 files ...
    branch //dev/branch/trunk/baz51a.java#4
    integrate //dev/branch/trunk/baz51b.java#2
    integrate //dev/branch/trunk/baz51c.java#2
    branch //dev/branch/trunk/baz51dev.java#3
    Change 27 submitted.
    

Compare the source and target branch files to confirm that a copy has been done.

$ p4 files //dev/branch/rel5.1/...
//dev/branch/rel5.1/baz51a.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51b.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51c.java#3 - edit change 12 (text)
//dev/branch/rel5.1/baz51dev.java#4 - add change 18 (text)

$ p4 files //dev/branch/trunk/...
//dev/branch/trunk/bar65a.java#3 - delete change 26 (text)
//dev/branch/trunk/bar65b.java#3 - delete change 26 (text)
//dev/branch/trunk/bar65c.java#3 - delete change 26 (text)
//dev/branch/trunk/baz51a.java#4 - branch change 27 (text)
//dev/branch/trunk/baz51b.java#2 - integrate change 27 (text)
//dev/branch/trunk/baz51c.java#2 - integrate change 27 (text)
//dev/branch/trunk/baz51dev.java#3 - branch change 27 (text)

All the bar files are deleted in the target 'trunk' branch since they did not exist in the 'rel5.1' source branch.

After the copy, the file content of file baz51a.java is the same in each branch.

$ cat ./rel5.1/baz51a.java 
class HelloWorld 
 public static void main(String[] args
 
 System.out.println("Hello 5.1 Development!")
 
 

$ cat ./trunk/baz51a.java
class HelloWorld 
 public static void main(String[] args
 
 System.out.println("Hello 5.1 Development!")
 
 
This confirms the baz51a.java file from the 'rel5.1' source branch really did copy over to the 'trunk' target branch.
 

NOTE ON USING p4 copy

If you are using the "p4 copy" command especially with labels, you might receive the following error:

can't branch existing file

You might want to use the "p4 integrate" command as described above instead.

Example comparing p4 copy with p4 integrate

1. Create a branch   
    [A]$ p4 branch -o AtoB
    # A Perforce Branch Specification.
    #
    #  Branch:      The branch name.
    #  Update:      The date this specification was last modified.
    #  Access:      The date of the last 'integrate' using this branch.
    #  Owner:       The user who created this branch.
    #  Description: A short description of the branch (optional).
    #  Options:     Branch update options: [un]locked.
    #  View:        Lines to map source depot files to target depot files.
    #
    # Use 'p4 help branch' to see more about branch views.
    
    Branch: AtoB
    
    Update: 2012/06/18 18:30:35
    
    Access: 2013/03/29 10:47:17
    
    Owner:  bruno
    
    Description:
            Created by bruno.
    
    Options:        unlocked
    
    View:
            //depot/A/... //depot/B/...
            -//depot/A/wowser.txt //depot/C/wowser.txt
    
2. Create a label named AB that is a subset of the files in //depot/A
    [dev]$ cd A                                                                                 
    [A]$ ls                                                                                              
    eof1.txt  eof1.txt~  eof.txt  eof.txt~  hello.txt  ktext.txt  ktext.txt~    

    [A]$ p4 tag -l AB hello.txt
    //depot/A/hello.txt#1 - added                

    [A]$ p4 tag -l AB ktext.txt
    //depot/A/ktext.txt#1 - added                

    [A]$ p4 label -o AB        
    # A Perforce Label Specification.            
    #                                            
    #  Label:       The label name.              
    #  Update:      The date this specification was last modified.
    #  Access:      The date of the last 'labelsync' on this label.
    #  Owner:       The user who created this label.               
    #  Description: A short description of the label (optional).   
    #  Options:     Label update options: locked or unlocked.      
    #  View:        Lines to select depot files for the label.     
    #                                                              
    # Use 'p4 help label' to see more about label views.           
    
    Label:  AB
    
    Update: 2013/03/29 10:34:56
    
    Access: 2013/03/29 10:34:56
    
    Owner:  bruno
    
    Description:
            Created by bruno.
    
    Options:        unlocked noautoreload
    
    View:
            //testdepot/...          
            //depot/...             
          
3. Populate the label AB files in //depot/B
	    [A]$ p4 copy -b AtoB //depot/...@AB      
	    //depot/B/hello.txt#1 - branch/sync from //depot/A/hello.txt#1
	    //depot/B/ktext.txt#1 - branch/sync from //depot/A/ktext.txt#1

	    [A]$ p4 submit -d "AB branch"               
	    Submitting change 24234.                                     
	    Locking 2 files ...                                           
	    branch //depot/B/hello.txt#1                                 
	    branch //depot/B/ktext.txt#1                                  
	    Change 24234 submitted.                                       
4. Make a change to one of the files, //depot/A/hello.txt
	
	    [A]$ p4 edit hello.txt
	    //depot/A/hello.txt#1 - opened for edit
	    ... //depot/A/hello.txt - also opened by fong@fong_ts-win7x64wq-vm_5084
	    ... //depot/A/hello.txt - also opened by bruno@frombliss               
	    ... //depot/A/hello.txt - also opened by bruno@transfer                

	    [A]$ vi hello.txt                                  

	    [A]$ p4 submit -d "adding an AB file"                
	    Submitting change 24235.                                               
	    Locking 1 files ...                                                    
	    edit //depot/A/hello.txt#2                                             
	    Change 24235 submitted.                                                

    FYI only, note that "can't branch existing file" already is in place but the -s flag will work
	    [A]$ p4 copy -b AtoB //depot/...@AB   
	    //depot/B/hello.txt - can't branch existing file        
	    //depot/B/ktext.txt - can't branch existing file        
	
	    [A]$ p4 copy -n -b AtoB -s //depot/...@AB
	    //depot/A/eof.txt#1 - delete from //depot/B/eof.txt#none   
	    //depot/A/eof1.txt#1 - delete from //depot/B/eof1.txt#none
	    //depot/A/hello.txt#2 - delete from //depot/B/hello.txt#none
	    //depot/A/ktext.txt#1 - delete from //depot/B/ktext.txt#none
	    //depot/B/aloha1.txt#1 - delete from //depot/A/aloha1.txt#none
	
5. Make a change to the target (not the source) //depot/B/hello.txt and note that the -s flag behaves as expected
	    [A]$ p4 files //depot/...@AB                
	    //depot/A/hello.txt#1 - add change 24056 (text)               
	    //depot/A/ktext.txt#1 - add change 24056 (text)               

	    [A]$ p4 edit //depot/B/hello.txt
	    //depot/B/hello.txt#1 - opened for edit           

	    [A]$ echo "trying the -s flag" >> ../B/hello.txt

	    [A]$ p4 submit -d "adding the trying line"
	    Submitting change 24236.                                    
	    Locking 1 files ...                                         
	    edit //depot/B/hello.txt#2                                  
	    Change 24236 submitted.                  

	    [A]$ p4 copy -n -b AtoB -s //depot/...@AB
	    //depot/A/eof.txt#1 - delete from //depot/B/eof.txt#none   
	    //depot/A/eof1.txt#1 - delete from //depot/B/eof1.txt#none
	    //depot/A/hello.txt#2 - delete from //depot/B/hello.txt#none
	    //depot/A/ktext.txt#1 - delete from //depot/B/ktext.txt#none
	    //depot/B/aloha1.txt#1 - delete from //depot/A/aloha1.txt#none
	    //depot/B/hello.txt#2 - sync/integrate from //depot/A/hello.txt#1
	
	    [A]$ p4 revert //...
	    //... - file(s) not opened on this client.
	
FYI only, note that since label AB refers to the older version of //depot/B/hello.txt#1, integrate will say that revisions are already integrated.
	
	    [A]$ p4 integrate -b AtoB //depot/...@AB
	    All revision(s) already integrated.

	    [A]$ p4 files @AB
	    //depot/A/hello.txt#1 - add change 24056 (text)
	    //depot/A/ktext.txt#1 - add change 24056 (text)
	
6. Make a change to the source
	                      
	    [A]$ p4 edit ktext.txt                  
	    //depot/A/ktext.txt#1 - opened for edit                   

	    [A]$ echo "adding p4 copy test" >> ktext.txt

	    [A]$ p4 submit -d "adding p4 copy test"     
	    Submitting change 24237.                                      
	    Locking 1 files ...                                           
	    edit //depot/A/ktext.txt#2                                    
	    Change 24237 submitted.                                      
	
	    [A]$ p4 tag -l AB //depot/A/ktext.txt#2
	    //depot/A/ktext.txt#2 - updated

7. Try "p4 integrate" and "p4 copy"
	    [A]$ p4 integrate -b AtoB //depot/...@AB
	    //depot/B/ktext.txt#1 - integrate from //depot/A/ktext.txt#2

    This works as expected.  The copy command has an error if files are already open.  We will revert any files open.
 	
	    [A]$ p4 copy -n -b AtoB //depot/...@AB
	    Can't copy to target path with files already open.

	    [A]$ p4 revert //...
	    //depot/B/ktext.txt#1 - was integrate, reverted
	
Environment is now set up.  A target file has changed. A source file has changed.  And we are integrating using a branch spec path which is further filtered by the files in the label.

8. Try "p4 integrate"
	    [A]$ p4 integrate -n -b AtoB //depot/...@AB
	    //depot/B/ktext.txt#1 - integrate from //depot/A/ktext.txt#2
	
    This works as expected.

9. Try "p4 copy"
	    [A]$ p4 copy -n -b AtoB //depot/...@AB
	    //depot/B/hello.txt#1 - branch/sync from //depot/A/hello.txt#1
	    //depot/B/ktext.txt - can't branch existing file

	    This does not work as expected because of "can't branch existing file".  
        Would like to see no error and a straight copy.

10. Try "p4 copy -s"
	   [A]$ p4 copy -n -b AtoB -s //depot/...@AB
	    //depot/A/eof.txt#1 - delete from //depot/B/eof.txt#none
	    //depot/A/eof1.txt#1 - delete from //depot/B/eof1.txt#none
	    //depot/A/hello.txt#2 - delete from //depot/B/hello.txt#none
	    //depot/A/ktext.txt#2 - delete from //depot/B/ktext.txt#none
	    //depot/B/aloha1.txt#1 - delete from //depot/A/aloha1.txt#none
	    //depot/B/hello.txt#2 - sync/integrate from //depot/A/hello.txt#1
	    //depot/B/ktext.txt#1 - sync/integrate from //depot/A/ktext.txt#2

	    [A]$

This approach works as expected, but note the deletes are also propagated because the -s flag states "Treat fromFile as the source and both sides of the branch  view to as the target." as explained  https://www.perforce.com/perforce/doc.current/manuals/cmdref/index.html#CmdRef/p4_copy.html
Related Links

Feedback

 

Was this article helpful?


   

Feedback

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

Characters Remaining: 255