Perforce Public Knowledge Base - Merging Changes Between Unrelated Codelines
Downloads Blog Company Integrations Careers Contact Try Free
Menu Search
Reset Search



Merging Changes Between Unrelated Codelines

« Go Back



How do I merge changes between codelines that are not branched from each other?


Consider the following situation. You have two codeline paths B and C, each of which was originally branched from the same path, A. The files in paths B and C are therefore not directly related to each other by branching, although they do share a common ancestor:

            B  +---------------------------
	A ---+-----+-----------------------
		  C  +---------------------

How do you integrate (merge) changes between files in these sibling paths? The simplest answer is that you run the p4 integrate command. For example:

p4 integ B/... C/...

However, the first time you do this you might not get the desired result. Perforce uses integration history created by previous integration commands to know which file revisions to integrate. Since C was not branched from B, there is no integration history between these two paths. So what happens when you try to integrate between them? The answer depends on whether you are using Release 2004.2 (or later), Release 2002.2 to 2003.2, Releases 99.2 through 2002.1, or a pre-99.2 release.

Release 2004.2 (or later)

Nothing extra need be done as p4 integrate for release 2004.2 and later always considers indirect integrations through intermediate branches when determining that files are related and what changes need to be integrated. The direct/indirect option in branch specifications has been removed as all integrations are considered indirect. Also, p4 integrate might select a base for merge resolution from a common ancestor which is neither the source nor the target file.

Release 2002.2 to 2003.2

When you attempt to integrate between source and target paths, no files are opened for integrate unless previous source-to-target history exists. By default, Perforce does not open a file for integrate unless it can find a base revision to use for a 3-way merge. Base revisions are chosen according to integration history, so when there is no integration history Perforce detects a "baseless" merge. As of Release 99.2, baseless merges are not permitted. To override this default, use the -i flag, for example:

p4 integ -i B/... C/...

The -i flag enables indirect integration -- it causes Perforce to search indirect integration history, attempting to find a suitable common ancestor in the source codeline. If it fails to find a suitable common ancestor, it falls back on the behavior of releases 99.2 through 2002.1.

In P4Win 2002.2 (or later), use the "Enable indirect merges" option of the Integrate dialog.

p4 integ -i and Releases 99.2 through 2002.1

In releases 99.2 through 2002.1, the -i flag enables baseless merges -- it makes Perforce open the target file for integrate, if it exists, and if no integration history exists between the source and the target, the starting integration revision of the source file is used as the base revision for a 3-way merge.

In our example, when you use -i, the C files are opened for integrate and, for each B-C file pair, B#1 is used as the base revision in a 3-way merge. After you p4 resolve and p4 submit, integration history shows that revision B#1 is already integrated into C -- that is all Perforce needs in selecting a base revision for future B-to-C integrations. (Actually, it is a simplification to say that B#1 is the key factor -- see Determining Revisions to Integrate for more information.)

In P4Win 99.2 through 2002.1, use the "Enable baseless merges" option of the Integrate dialog.

Pre-99.2 releases

When you integrate between source and target paths in pre-99.2 releases, the target file -- if it exists -- is opened for integrate regardless of previous source-to-target integration history. However, unless history shows that revision #1 of the source file was already integrated, the scheduled resolve does a 2-way merge, not a 3-way merge. In a 2-way merge there is no base, and although you can diff the two files ("theirs" and "yours") you cannot tell which changes were made by whom.

So, in the B-C example, the C files are opened for integrate, and a resolve is scheduled for each B-C file pair. When you resolve, you have to choose to keep either B#head or C#have. After you submit, integration history shows that B#head was integrated into C. But there is still no integration record for B#1 into C, so the next time you integrate, you are faced with the same problem.

There are ways to:

  • Make p4 integrate perform a 3-way merge even when revision #1 of the source has not been previously integrated, and
  • Set the base revision permanently so that integration history shows #1 was integrated, and subsequent integrations behave normally.

The remainder of this article explains how to perform the above tasks. Please refer to Determining Revisions to Integrate for background information about how Perforce determines which revisions need integrating.

Making p4 integrate perform a 3-way merge

In Release 99.2 and later you can simply use p4 integrate -i to coerce a 3-way merge. In earlier releases, the only way to coerce a 3-way merge is to supply a revision range to the integrate command. Perforce uses the revision range to compute the starting and ending source revisions to integrate. Once it knows the starting revision, it can determine which source revision to use as a base for a 3-way merge.

Going back to the example above, two changelists, 555 and 556, have been submitted into the B codeline path since it was branched from A. To integrate those changes directly into the C path, you can use the syntax:

p4 integrate B/...@555,@556 C/...
	p4 resolve
	p4 submit

Perforce identifies all the B files affected by changelists 555 and 556, and opens the corresponding C files for integrate. When you do the resolve, Perforce does a 3-way merge. For each B file merged into a corresponding C file, the base used for the 3-way merge is revision @554 -- that is, the predecessor to the starting revision being integrated is used as the merge base.

Alternatively, if you want to integrate all changes from B into C and you know the first changelist submitted into B was 555, you can use:

p4 integrate B/...@555, C/...
	p4 resolve
	p4 submit

Note the trailing comma in the revisions spec -- this syntax is short for:

p4 integrate B/...@555,#head C/...

Setting the base revision permanently

Unless integration history shows that the #1 revisions of the B files have already been integrated into C, you have to use revision ranges every time you integrate from B to C. In pre-99.2 releases, you have to first integrate just the #1 revisions, and submit those, to permanently set the base revisions to use for subsequent integrations.

Here is one way to accomplish this task. In this example, the files in the A path were branched into B in changelist 500. In other words, the B/...@500 files are all at their #1 revisions. To set the starting revision to use for future integrations from B to C, you can do an "ignore integrate" of B/...@500 into C:

p4 integrate B/...@500 C/...
	p4 resolve -ay
	p4 submit

The above p4 integrate command restricts the ending revision of each source file to @500. Using p4 resolve -ay ("accept yours") satisfies the resolve by ignoring any diffs; the contents of the target file are unchanged. Neverthess, for each C file submitted, Perforce records the fact that its corresponding B#1 file has been integrated. The next time you integrate, the B#2 file is used as the starting revision, and the B#1 file is used as the base in a 3-way merge.

If you also plan to integrate changes from C back into B, you can set permanent base revisions to use for future integrations in that direction as well. For example, if C was branched from A in changelist 600, you use:

p4 integrate C/...@600 B/...
	p4 resolve -ay
	p4 submit

"#1" vs. changelist number as starting revision

You might be asking yourself why you cannot set a permanent base revision using "#1" instead of a changelist number in the integrate command. In other words, why not use:

p4 integrate C/...#1 B/...
	p4 resolve -ay
	p4 submit

The above might work just as well for you, depending on how your codelines evolved, and what you are trying to accomplish. The difference between the two revision specification syntaxes is that C/...@600 includes only the files that were originally branched from A into C in changelist 600, whereas C/...#1 includes all the files that were ever submitted into the C path, including those added directly, and those branched from other codelines.

Related Links



Was this article helpful?



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

Characters Remaining: 255