File conflicts can occur when two users edit and submit two versions of the same file. A conflict can occur in a number of ways, but the situation is usually a variant of the following situation:
foo
for edit;
User 2 opens the same file in her client for edit;
User 1 and user 2 both edit their client workspace versions of foo
;
User 1 submits a changelist containing that file, and the submit succeeds;
User 2 submits a changelist with her version of the file; her submit fails.p4 get
, then the resolve is performed with p4 resolve
. RCS Format: How Perforce Stores File Revisions
Perforce uses RCS format to store its text file revisions; binary file revisions are always saved in full. If you already understand what this means, you can skip to the next section of this chapter; the remainder of this section explains how RCS format works. Only the Differences Between Revisions are Stored
A single file might have hundreds, even thousands, of revisions. Every revision of a particular file must be retrievable, and if each revision was stored in full, disk space problems could occur: one thousand 10KB files, each with a hundred revisions, would use a gigabyte of disk space. The scheme used by most SCM systems, including Perforce, is to save only the latest revision of each file, and then store the differences between each file revision and the one previous.foo
. The head revision (foo#3
) looks like this:
foo#3: |
---|
This is a test of the emergency broadcast system
|
Revision two might be stored as a symbolic version of the following:
foo#2: |
---|
line 3 was "urgent"
|
And revision 1 would be a representation of this:
foo#1: |
---|
line 3 was "system"
|
This is a test of the urgent system
|
The
RCS
(R
evision C
ontrol S
ystem) algorithm, developed by Walter Tichy, uses a notation for implementing this system that requires very little storage space and is quite fast. In RCS terminology, it is said that the full text of the head revisions are stored, along with the reverse deltas of each previous revision. Use of `diff' to Determine File Revision Differences
RCS utilizes the `GNU diff
' program to determine the differences between two versions of the same file. GNU diff
, (and therefore RCS
, and therefore Perforce), always determines file differences on a line-by-line basis. diff
must also be made available on NT Perforce servers; it can be downloaded from
<http://www.perforce.com/perforce/loadsupp.html>.Because
diff
always finds file deltas on a line-by-line basis, it will only work with text files. If a file is binary, it will always be stored in full.RCS is owned by Purdue University, and is available under the GNU copyright. For more information about RCS, please see
<http://www.cs.purdue.edu/homes/hammer/rcs.html>.
In slightly more technical terms: we'll call the file revision that was read into a client workspace the base file revision. If the base file revision for a particular file in a client workspace is not the same as the head revision of the same file in the depot, a resolve must be performed before the new file revision can be accepted into the depot.
Before resolves can be performed with
p4 resolve
, they must be scheduled. Resolves are always scheduled with p4 get
.
p4 get
command is named somewhat misleadingly: the job of p4 get
is to project the state of the depot onto the client. Thus, when p4 get
is performed on a particular file:
p4 edit
, the Perforce server can't simply copy the file onto the client: any changes that had been made to the current revision of the file in the client would be overwritten. Instead, a resolve is scheduled between the file revision in the depot, the file on the client, and the base file revision (the revision that was last read into the client).
*.guide
files in the elm doc
subdirectory. He has retrieved the //depot/elm_proj/doc/*.guide
files into his client and opened the files with p4 edit
. He edits the files, but before he has a chance to submit them, Lisa submits new versions to the depot of some of the same files. The versions Ed has been editing are no longer the head revisions; resolves must be scheduled and performed for each of the conflicting files before Ed's edits can be accepted. Ed schedules the resolves with p4 get //edk/doc/*.guide
. Since these files are already open in the client, Perforce doesn't replace the client files; instead, Perforce schedules resolves between the client files and the head revisions in the depot.
p4 submit
will fail if it determines that any of the files in the submitted changelist need to be resolved, and the error message will include the names of the files that need resolution. If the changelist provided to p4 submit
was the default changelist, it will be assigned a number, and this number must be used in all future references to the changelist.Another method is to run
p4 get -n
filepatterns before performing the submit, using the files in the changelist as arguments to the command. If file conflict resolutions are necessary, p4 get -n
will report them. The only advantage of this scheme over viewing the submit error is that the default changelist will not be assigned a number.
p4 resolve
[filepatterns]. Each file provided as an argument to p4 resolve
is processed separately. p4 resolve
starts with three revisions of the same file and generates a fourth version; the user can edit or accept any of these revisions in place of the current client file. The new revisions must then be submitted with p4 submit
.
p4 resolve
is interactive; a series of options are displayed for the user to respond to. The dialog looks something like this:
/usr/edk/elm/doc/answer.1 - merging //depot/elm_proj/doc/answer.1#5 Diff chunks: 4 yours + 2 theirs + 1 both + 1 conflicting Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [e]: |
The remainder of this section explains what this means, and how to use this dialog.
File Revisions Used and Generated by p4 resolve
p4 resolve
[filepatterns] starts with three revisions of the same file, generates a new version that merges elements of all three revisions, allows the user to edit the new file, and writes the new file (or any of the original three revisions) to the client. The file revisions used by p4 resolve
are these:
The remainder of this chapter will use the terms theirs, yours, base, merge, and result to refer to the corresponding file revisions. The definitions given above are somewhat different when resolve is used to integrate branched files.
Types of Conflicts Between File Revisions
The diff
program that underlies the Perforce resolve mechanism determines differences between file revisions on a line-by-line basis. Once these differences are found, they are grouped into line sets: for example, three new lines that are adjacent to each other are grouped into a single set. Yours and theirs are both generated by a series of edits to base; for each set of lines in yours, theirs, and base, p4 resolve
asks the following questions:
p4 resolve
in this form:
2 yours + 3 theirs + 1 both + 5 conflictingIn this case, two line sets are identical in theirs and base but are different in merge; three line sets are identical in yours and base but are different in theirs; one line set was changed identically in yours and theirs; and five line sets are different in yours, theirs, and base.
p4 resolve
generates a preliminary version of the merge file, which can either be accepted as is, edited and then accepted, or rejected. A simple algorithm is followed to generate this file: any changes found in yours, theirs, or both yours and theirs are applied to the base file and written to the merge file; and any conflicting changes will appear in the merge file in the following format:
>>>> ORIGINAL VERSION
(text from the original version)
==== THEIR VERSION
(text from their file)
==== YOUR VERSION
(text from your file)
<<<<
Thus, editing the Perforce-generated merge file is often as simple as opening the merge file, searching for the difference marker `
>>>>'
, and editing that portion of the text. However, this is not always the case; it's often useful (and necessary) to examine the changes made to theirs to make sure they're compatible with the changes you made.
p4 resolve
command offers the following options:
Only a few of these options are visible on the command line, but all options are accessible and can be viewed by choosing
help
.
Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [am]:Perforce's recommended choice is displayed in brackets at the end of the command line. Pressing
return
or choosing Accept
will perform the recommended command. The recommended command is chosen by Perforce by the following algorithm: if there were no changes to yours, accept theirs. If there were no changes to theirs, accept yours. Otherwise, accept merge.In the last example, Ed scheduled the
doc/*.guide
files for resolve. This was necessary because both he and Lisa had been editing the same files; Lisa had already submitted versions, and Ed needs to reconcile his changes with Lisa's. To perform the resolves, he types p4 //depot/elm_proj/doc/*.guide
, and sees the following:
/usr/edk/elm/doc/Alias.guide - merging //depot/elm_proj/doc/Alias.guide#5 Diff chunks: 4 yours + 2 theirs + 1 both + 1 conflicting Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [e]: |
This is the resolve dialog for
doc/Alias.guide
, the first of the four doc/*.guide
files. Ed sees that he's made four changes to the base file that don't conflict with any of Lisa's changes; he also notes that Lisa has made two changes that he's unaware of. He types dt
(for "display theirs") to view Lisa's changes; he looks them over and sees that they're fine. Of most concern to him, of course, is the one conflicting change. He types e
to edit the Perforce-generated merge file and searches for the difference marker `>>>>'
. The following text is displayed:
Intuitive Systems Mountain View, California >>>> ORIGINAL VERSION ==== THEIR VERSION 98992 ==== YOUR VERSION 98993 <<<< |
He and Lisa have both tried to add a zip code to an address in the file; Ed had typed it wrong. He changes this portion of the file so it reads as follows:
Intuitive Systems Mountain View, California 98992 |
The merge file is now acceptable to him: he's viewed Lisa's changes, seen that they're compatible with his own, and the only line conflict has been resolved. He quits from the editor and types
am
; the edited merge file is written to the client, and the resolve process continues on the next doc/*.guide
file.When a version of the file is accepted onto the client, the previous client file is overwritten, and the new client file must still be submitted to the depot. Note that it is possible for another user to have submitted yet another revision of the same file to the depot between the time
p4 resolve
completes and the time p4 submit
is performed; in this case, it would be necessary to perform another resolve. This can be prevented by locking the file before performing the resolve.
p4 resolve
flags tell the command to work non-interactively; when these flags are used, particular revisions of the conflicting files will be automatically accepted.
Ed has been editing the
doc/*.guide
files, and knows that some of them will require resolving. He types p4 get doc/*.guide
; all of these files that conflict with files in the depot are scheduled for resolve. He then types p4 resolve -am
; the merge files for all scheduled resolves are generated, and those merge files that contain no line set conflicts are written to his client workspace. He'll still need to manually resolve all the other conflicting files, but the amount of work he needs to do is substantially reduced. Binary Files and p4 resolve
If any of the three file revisions participating in the merge are binary instead of text, a three-way merge is not possible. Instead, p4 resolve
simply presents the two conflicting file versions, allows you to edit them, and choose between them. Locking Files to Minimize File Conflicts
Once open, a file can be locked with p4 lock
so that only the user who locked the file can submit the next revision of that file to the depot. Once the file is submitted, it is automatically unlocked, and a locked file can be manually unlocked by the locking user with p4 unlock
.p4 lock
is that once a file is locked, the user who locked it will experience no further conflicts on that file, and will not need to resolve the file. But this comes at a price: other users will not be able to submit the file until the file is unlocked, and will have to do their own resolves once they submit their revision. Under most circumstances, a user who locks a file is essentially saying to the other users "I don't want to deal with any resolves; you deal with them." But there is an exception to that rule. Preventing Multiple Resolves with File Locking
Without file locking, there is no guarantee that the resolve process will ever end. The following scenario demonstrates the problem:foo
for edit;
User 2 opens the same file in her client for edit;
User 1 and user 2 both edit their client workspace versions of foo
;
User 1 submits a changelist containing that file, and his submit succeeds;
User 2 submits a changelist with her version of the file; her submit
fails because of file conflicts with the new depot's foo
;
User 2 starts a resolve;
User 1 edits and submits a new version of the same file;
User 2 finishes the resolve and attempts to submit; it fails and must now
be merged with User 1's latest file.
<etc...> Resolves and Branching
Files in separate branches can be integrated with p4 resolve
. An additional command, p4 reresolve
, can be useful in this context. Resolve Reporting
Four reporting commands are related to file conflict resolution: p4 diff
, p4 diff2
, p4 get -n
, and p4 resolved
.