Specifics of FCM
This aims to explain and provide tutorial examples for the following topics:
Now lets do the Specificss Quiz if you have not already done it at the end of the Essentials section to see how much you already know and what we will need to focus on in this section.
Repository setup
Please run the following tutorial repositories script if you have not already done so by running the script it will set-up the repositories that you will need for all of the tutorials. WARNING: This script adds and creates if required keywords the file ~/.metomi/fcm/keywords.cfg if the file already exists it copies the orginal to ~/.metomi/fcm/keywords_orig1.cfg. If you rerun the script it will do the same but re-number older versions of the configuation file keeping all version. Please monitor the number of these that you have and tidy up the folder periodically keeping only the desired versions.
If at any stage the repository gets corrupted then we can start again:
cd # Warning this tearsdown the whole repository to start from scratch. rm -rf ~/fcm_tutorial rm -rf ~/my_fcm_tutorial # The tutorial repositories script tutorial_repo_setup
All of the tutorial sections are separate and do not depend on each other therefore it is safe to teardown the repositories. The only issue may be that the revision numbers do not match, but that is not important for the tutorials.
Specifics Tutorials I
fcm merge --custom (--revision)
If --custom
is specified as an option to fcm merge
,
then the command can be used in one of two forms:
fcm merge --custom --revision N:M SOURCE
This is a custom merge, it performs a custom merge from the specified changeset(s) of SOURCE into the working copy. The SOURCE must be a valid URL[@REV] of a branch. If a single revision is specified, the merge delta is (N - 1):N of the SOURCE. Otherwise, the merge delta is N:M of SOURCE, where M < N.fcm merge --custom URL1@REV1 URL2@REV2
This is custom merge using the delta between the two specified branch URLs. For each URL, if a revision is not specified, the command will use the URL with the last changed revision.
How can we find out what version of the trunk the branch branch_merge_custom was created from?
How can we compare and find out what changes have been made to the the branch branch_merge_custom2 which was created from the now HEAD of the trunk, which has been updated since the branch was created from the trunk?
cd ~/my_fcm_tutorial/specifics/branch_merge_custom
fcm info
Path: .
Working Copy Root Path: /net/$HOME/my_fcm_tutorial/specifics/branch_merge_custom
URL: file:///$HOME/fcm_tutorial/repository/specifics/branches/dev/$LOGNAME/r36_branch_merge_custom
Relative URL: ^/specifics/branches/dev/$LOGNAME/r36_branch_merge_custom
Repository Root: file:///$HOME/fcm_tutorial/repository
Repository UUID: 0ab956ee-d466-4a5f-b005-2573ac924882
Revision: 37
Node Kind: directory
Schedule: normal
Last Changed Author: $LOGNAME
Last Changed Rev: 37
Last Changed Date: 2016-02-02 16:33:58 +0000 (Tue, 02 Feb 2016)
fcm log -v
------------------------------------------------------------------------
r37 | $LOGNAME | 2016-02-02 16:42:29 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/branches/dev
A /specifics/branches/dev/$LOGNAME
A /specifics/branches/dev/$LOGNAME/r36_branch_merge_custom (from /specifics/trunk:36)
Made a branch Created file:///$HOME/fcm_tutorial/repository/specifics/branches/dev/$LOGNAME/r36_branch_merge_custom from /trunk@31.
------------------------------------------------------------------------
r36 | $LOGNAME | 2016-02-02 16:42:29 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/etc/readme.txt
A /specifics/tree_conflict.txt
These changes to the trunk are for setting up a trunk repository so that it has all the files and directories that are needed for the Specifics tutorial section.
------------------------------------------------------------------------
r35 | $LOGNAME | 2016-02-02 16:42:28 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/etc
Adding the pin/ directory.
------------------------------------------------------------------------
r34 | $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/lib/readme_only.py
Change made to correct the properties on readme_only.py using propdel svn:executable
------------------------------------------------------------------------
r33 | $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/ever_growing_file.dat
Change made to provide a .dat file that we would want to ignore using propset svn:ignore
------------------------------------------------------------------------
r32 | $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics/lib
A /specifics/lib/my_hello_script.py
Change made to correct the properties on my_hello_script.py using propset svn:executable ON
------------------------------------------------------------------------
r30 | $LOGNAME | 2016-02-02 16:42:25 +0000 (Tue, 02 Feb 2016) | 1 line
Changed paths:
A /specifics
New folder specifics
------------------------------------------------------------------------
cd ~/my_fcm_tutorial/specifics
fcm sw fcm fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_merge_custom2
fcm info
Path: .
Working Copy Root Path: /net/$HOME/my_fcm_tutorial/specifics/r36_branch_merge_custom2
URL: file:///$HOME/fcm_tutorial/repository/specifics/r36_branch_merge_custom2
Relative URL: ^/specifics/r_36branch_merge_custom2
Repository Root: file:///$HOME/fcm_tutorial/repository
Repository UUID: 0ab956ee-d466-4a5f-b005-2573ac924882
Revision: 55
Node Kind: directory
Schedule: normal
Last Changed Author: $LOGNAME
Last Changed Rev: 55
Last Changed Date: 2016-02-02 16:42:34 +0000 (Tue, 02 Feb 2016)
fcm log -v
------------------------------------------------------------------------
r55 | $LOGNAME | 2016-02-06 16:45:45 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/branches/dev/$LOGNAME/r36_branch_merge_custom2 (from /specifics/trunk:54)
Made a branch Created file:///$HOME/fcm_tutorial/repository/specifics/branches/dev/$LOGNAME/r36_branch_merge_custom2 from /trunk@31.
------------------------------------------------------------------------
r54 | $LOGNAME | 2016-02-06 16:45:45 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
M /specifics/etc/amazing_rock.txt
Adding more to the list of amazing rock bands.
------------------------------------------------------------------------
r53 | $LOGNAME | 2016-02-06 16:45:44 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
M /specifics/etc/90s_pop.txt
Adding a honest comment to the file etc/90s_pop.txt.
------------------------------------------------------------------------
r52 | $LOGNAME | 2016-02-06 16:45:44 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/etc/90s_pop.txt
Adding a list of my fav 90's pop bands.
------------------------------------------------------------------------
r51 | $LOGNAME | 2016-02-06 16:45:44 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
M /specifics/etc/amazing_rock.txt
This list is endless but it needed some amazing oldies.
------------------------------------------------------------------------
r50 | $LOGNAME | 2016-02-06 16:45:44 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/etc/amazing_rock.txt
Adding a list of the rock bands that I enjoy.
------------------------------------------------------------------------
r49 | $LOGNAME | 2016-02-06 16:45:44 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/etc
Adding the etc/ directory.
------------------------------------------------------------------------
r36 | $LOGNAME | 2016-02-06 16:45:41 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/etc/readme.txt
A /specifics/tree_conflict.txt
These changes to the trunk are for setting up a trunk repository so that it has all the files and directories that are needed for the Specifics tutorial section.
------------------------------------------------------------------------
r35 | $LOGNAME | 2016-02-06 16:45:40 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/etc
Adding the pin/ directory.
------------------------------------------------------------------------
r34 | $LOGNAME | 2016-02-06 16:45:39 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/lib/readme_only.py
Change made to correct the properties on readme_only.py using propdel svn:executable
------------------------------------------------------------------------
r33 | $LOGNAME | 2016-02-06 16:45:39 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/ever_growing_file.dat
Change made to provide a .dat file that we would want to ignore using propset svn:ignore
------------------------------------------------------------------------
r32 | $LOGNAME | 2016-02-06 16:45:39 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics/lib
A /specifics/lib/my_hello_script.py
Change made to correct the properties on my_hello_script.py using propset svn:executable ON
------------------------------------------------------------------------
r30 | $LOGNAME | 2016-02-06 16:45:38 +0000 (Sat, 06 Feb 2016) | 1 line
Changed paths:
A /specifics
New folder specifics
------------------------------------------------------------------------
Here we want to only merge in the adding of the etc/ directory and "Rock" commits 1 and 2.
How do you think we can merge just these changes using the command above?
cd ~/my_fcm_tutorial/specifics
fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_merge_custom
fcm merge --custom --revision 48:52 fcm:fcm_sp_br/dev/$LOGNAME/r36_branch_merge_custom2
-------------------------------------------------------------------------dry-run
--- Merging r48 through r52 into '.':
A etc
A etc/amazing_rock.txt
-------------------------------------------------------------------------dry-run
Would you like to go ahead with the merge?
Enter "y" or "n" (or just press <return> for "n"): y
Merge succeeded.
--------------------------------------------------------------------------actual
--- Merging r48 through r52 into '.':
A etc
A etc/amazing_rock.txt
--- Recording mergeinfo for merge of r48 through r52 into '.':
U .
--------------------------------------------------------------------------actual
We want to only merge in the Rock commit 3.
How do you think we can do this using the command above?
fcm merge --custom fcm:fcm_sp_br/dev/$LOGNAME/r36_branch_merge_custom2@53 fcm:fcm_sp_br/dev/$LOGNAME/r36_branch_merge_custom2@54
merge: status of ".":
M .
A + etc
merge: continue?
Enter "y" or "n" (or just press <return> for "n"): y
-------------------------------------------------------------------------dry-run
--- Merging r54 into '.':
U etc/amazing_rock.txt
-------------------------------------------------------------------------dry-run
Would you like to go ahead with the merge?
Enter "y" or "n" (or just press <return> for "n"): y
Merge succeeded.
--------------------------------------------------------------------------actual
--- Merging r54 into '.':
U etc/amazing_rock.txt
--- Recording mergeinfo for merge of r562 into '.':
G .
--------------------------------------------------------------------------actual
fcm propset svn:execuatable
We have added a file without changing the permissions on that file before committing it back to the repository.
The next time that this file is checked out it will not have the permissions that we require.
We can change the permissions to executable by using:
fcm propset|pset|ps svn:execuatable ON <FILENAME>
Next time that we commit changes to the repository it will change the file permissions on that file.
cd ~/my_fcm_tutorial/specifics fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_propset_exe cd lib ls -ltr total 4 -rw-r--r-- 1 $LOGNAME users 41 Feb 2 16:42 my_hello_script.py -rwxr-xr-x 1 $LOGNAME users 72 Feb 2 16:42 readme_only.py # Note "my_script.py" does not have executable on it. # We need to change this so when it is checkout again the permission are # correct. fcm ps svn:executable ON my_hello_script.py ls -ltr total 4 -rwxr-xr-x 1 $LOGNAME users 41 Feb 2 16:42 my_hello_script.py -rwxr-xr-x 1 $LOGNAME users 72 Feb 2 16:42 readme_only.py # Make another change to the repository, add another python script but set the # permissions correct before we commit it to the repository. cat > my_goodbye_script.py << EOF /usr/bin/env python print 'Goodbye for now' EOF chmod 755 my_goodbye_script.py # Check the status of the branch fcm st ? my_goodbye_script.py M my_hello_script.py
What do the returned statuses mean and what action if any do you need to take?
'?' means it is not under version control so we must add it.
fcm add my_goodbye_script.py
' M' means the properties are modified and no action is needed by us.
fcm ci
[info] vi: starting commit message editor...
Change summary:
--------------------------------------------------------------------------------
[Root : file:///$HOME/fcm_tutorial/repository]
[Project: specifics]
[Branch : branches/dev/$LOGNAME/r36_branch_propset_exe]
[Sub-dir: ]
A lib/my_goodbye_script.py
M lib/my_hello_script.py
--------------------------------------------------------------------------------
Commit message is as follows:
--------------------------------------------------------------------------------
Changed the properties of lib/my_hello_script.py and added a new script.
--------------------------------------------------------------------------------
Would you like to commit this change?
Enter "y" or "n" (or just press <return> for "n"): y
Adding lib/my_goodbye_script.py
Sending lib/my_hello_script.py
Transmitting file data .
Committed revision 56.
Updating '.':
At revision 56.
Now we have changed the executable properties on the my_hello_script.py script.
If we checked in/committed the branch it would have the correct properties. Note that as the trunk has the wrong properties for my_hello_script.py then all of the other branches created from it will have the wrong properties.
We should merge our change into the trunk to correct this. Do this now.
fcm propset svn:ignore
We want to ignore a file in the repository that we are working on as the file is needed but is not to be associated with the repository as it is very big or we keep updating it.
fcm propset|ps svn:ignore <FILENAME> .
cd ~/my_fcm_tutorial/specifics
fcm sw fcm:fcm_sp/branches/dev/r36_branch_propset_ign
# export SVN_EDITOR='gvim -f'
fcm st
fcm ps svn:ignore "ever_growing_file.dat" .
fcm st
M .
# Note the dot at the end of the line. It tells SVN that the property is being set on the current directory.
FCM will now ignore the file ever_growing_file.dat.
We can check this using:
fcm propget svn:ignore .
ever_growing_file.dat
This show us the list of the files at are being ignored in the current directory.
fcm propdel svn:execuatable
We can remove the executable permissions on a file by:
fcm propdel|pdel|pd svn:executable <FILENAME>
Next time that we commit changes to the repository it will change the file permissions on that file.
cd ~/my_fcm_tutorial/specifics fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_propdel/lib ls -ltr total 4 -rw-r--r-- 1 $LOGNAME users 41 Feb 2 16:42 my_hello_script.py -rwxr-xr-x 1 $LOGNAME users 72 Feb 2 16:42 readme_only.py # Note "readme_only.py" has executable on it and it should be read only. # We need to change this so when it is checkout again the permission are # correct. fcm pd svn:executable readme_only.py property 'svn:executable' deleted from 'readme_only.py'. ls -ltr total 4 -rw-r--r-- 1 $LOGNAME users 41 Feb 2 16:42 my_hello_script.py -rw-r--r-- 1 $LOGNAME users 72 Feb 2 16:42 readme_only.py # Make another change to the repository, add another python script but set the # permissions correct before we commit it to the repository. cat > readme2.py << EOF /usr/bin/env python print 'Another readme script.' EOF
What do we need to do before we commit back to the repository?
fcm st
? readme2.py
M readme_only.py
# What does the ' M' for readme_only.py mean? See above in fcm propset svn:execuatable
fcm add readme2.py
fcm ci
/net/$HOME/my_fcm_tutorial/specifics/branch_propde: working directory changed to top of working copy.
[info] gvim -f: starting commit message editor...
Change summary:
--------------------------------------------------------------------------------
[Root : file:///$HOME/fcm_tutorial/repository]
[Project: specifics]
[Branch : branches/dev/$LOGNAME/r36_branch_propde]
[Sub-dir: ]
A lib/readme2.py
M lib/readme_only.py
--------------------------------------------------------------------------------
Commit message is as follows:
--------------------------------------------------------------------------------
Changed the properties of lib/readme_only.py and lib/added readm2.py.
--------------------------------------------------------------------------------
Would you like to commit this change?
Enter "y" or "n" (or just press <return> for "n"): y
Adding lib/readme2.py
Sending lib/readme_only.py
Transmitting file data .
Committed revision 56.
Updating '.':
At revision 56.
Now we have changed the executable properties on the readme_only.py script.
If we checked in/committed the branch it would have the correct properties. Note that as the trunk has the wrong properties for readme_only.py then all of the other branches created from it will have the wrong properties.
We should merge our change into the trunk to correct this.
propedit svn:log
We want to change a log entry as we made a mistake in it.
The general view is not to worry too much and to add a correction comment in the next commit message.
However, we can change it using/with:
fcm propedit|pedit|pe svn:log --revprop -r <REVISION> fcm:<KEYWORD>
fcm pe svn:log --revprop -r <REVISION> <URL>
or
fcm pe svn:log --revprop -r <REVISION> <BRANCH_URL>
cd ~/my_fcm_tutorial/specifics fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_propedit
One of the log commits has a typo. How can we find the typo?
-
fcm log
------------------------------------------------------------------------
r41 | $LOGNAME | 2016-02-02 16:42:30 +0000 (Tue, 02 Feb 2016) | 1 line
Made a branch Created file:///$HOME/fcm_tutorial/repository/specifics/branches/dev/$LOGNAME/r36_branch_propedit from /trunk@31.
------------------------------------------------------------------------
r36 | $LOGNAME | 2016-02-02 16:42:29 +0000 (Tue, 02 Feb 2016) | 1 line
These changes to the trunk are for setting up a trunk repository so that it has all the files and directories that are needed for the Specifics tutorial section.
------------------------------------------------------------------------
r35 | $LOGNAME | 2016-02-02 16:42:28 +0000 (Tue, 02 Feb 2016) | 1 line
Adding the etd/ directory.
------------------------------------------------------------------------
r34 |i $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Change made to correct the properties on readme_only.py using propdel svn:executable
------------------------------------------------------------------------
r33 | $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Change made to provide a .dat file that we would want to ignore using propset svn:ignore
------------------------------------------------------------------------
r32 | $LOGNAME | 2016-02-02 16:42:27 +0000 (Tue, 02 Feb 2016) | 1 line
Change made to correct the properties on my_hello_script.py using propset svn:executable ON
------------------------------------------------------------------------
r30 | $LOGNAME | 2016-02-02 16:42:25 +0000 (Tue, 02 Feb 2016) | 1 line
New folder specifics/trunk
------------------------------------------------------------------------
r35, "etd/" should be "/etc"
Now we can correct it.
export SVN_EDITOR="gvim"
fcm pe svn:log --revprop -r 35 fcm:fcm_sp_br/dev/${LOGNAME}/r36_branch_propedit
Set new value for property 'svn:log' on revision 35
This will correct the log message in the commit.
General about Trac and Tickets
Here we will cover the minimum information that is needed to understand Trac and Tickets.
Trac
Trac is a wiki system which we can use for organizing knowledge and information in a very flexible way that FCM has be designed to interact with. A brief summary on Trac:
- It is a flexible issue tracker.
- It provides a roadmap feature for managing project release, including a record of all changes included in the release.
- It has a built-in wiki.
- It lets us use a browser for viewing the Subversion repositories, where we can browse the project tree and files, examine revision logs and examine the changesets.
- It provides a timeline view with summaries of changes to: tickets, wiki pages and subversion repositories.
- It provides a flexible ticket workflow, this supports the review process and can be adapted to meet the requirements of larger systems. Trac in detail
fcm browse
If setup correctly on your site we can invoke the web-browser to launch the
corresponding URL of the web-based
repository browser (currently Trac browser).
fcm browse|trac|www <URL>
branch-diff -t
We can launch Trac with the default web browser to report the diff of a branch
using:
fcm branch-diff --trac|-t <URL|local/working copy>
Tickets
Tickets allow people to follow an issue, or a list of tickets matching the chosen criterion. Creating a ticket
Text conflicts
In Essentials tutorial III text conflicts we created a text conflict and resolved it.
The text conflict was created by?
- Creating two branches from the trunk and checking them out with different names.
- In "branch1" we appended to a text file some additional text. We then committed the change.
- In "branch2" we appended to a text file of the same name as in "branch1" some different additional text. We then committed the change.
- We then merged "branch1" into "branch2". This created a Text conflict.
fcm st
returns the following when there is a text conflict on the
repository:
C statusesC_text.txt
How did we resolve the text conflict?
fcm conflicts
Left clicked on the text option that we want to keep.
Then press "m", or use the toolbar; File -> Exit with MERGED M to merge the change.
Now we need to learn more about the command fcm conflicts
.
conflicts
The command fcm conflicts|cf
is a graphical tool to help
resolve conflicts within the local/working copy.
Note it cannot help with all conflicts.
It works with the most effectively with Text Conflicts.
A type of conflict that we may come across are "Text conflicts".
These are returned via fcm st
as
C statusesC_text.txt
where column 1 has a "C" in it.
To resolve the text conflict we use the 3-way difference tool xxdiff.
For each file with a text conflict, the fcm conflicts
command
calls a graphical merge tool (i.e. xxdiff by default) to display a 3-way diff.
How to use xxdiff to help resolve text conflicts
The file on the left is our original file. The file in the middle is the common ancestor from the merge. The file on the right is the file containing the changes which we are merging in.
A quick way of resolving the conflict (from Essentials tutorial III text conflicts):

# Left click on the text option that we want to keep, it should change colour from yellow to purple.
# Then press "m", or use the toolbar; File -> Exit with MERGED M.
Explanations of the three window split xxdiff:
The number on the far right panel of xxdiff tool is the number of unselected differences, known as "hunks" or "sections" and they are often seen in yellow. The correct term for the highlighted section is hunk, but here we will refer to it as the section as it is easier to understand and remember what we are talking about.
When this number is 0 then we are ready to save the merged file.
To see how the merged file will look with the current selections, click Windows->Toggle Merged View (keyboard shortcut: Alt+Y).
An extra window then appears showing the merged output that updates interactively as we make our selections.
Useful xxdiff keyboard shortcuts:
Everyday language:
p - previous change
n - next change
o - previous conflict
b - next conflict
m - accept merge the section that is left clicked on and exit.
a - accept and exit.
m - reject and exit.
FCM/correct language:
B - move to the next unselected section
O - move to the previous unselected section
To exit the 3-way diff (available from the File menu):
Exit with MERGE (keyboard shortcut: M)
Exit with ACCEPT (keyboard shortcut: A)
Exit with REJECT (keyboard shortcut: R)
If we just want to exit without making any decisions we can also just close the window.
If we have resolved all the conflicts in a file then we will be prompted on
whether to run svn resolved
on the file to signal that the file
is no longer in conflict.
fcm conflicts Conflicts in file: statusesC_text.txt You have chosen to ACCEPT all the changes Would you like to run "svn resolved"? Enter "y" or "n" (or just pressfor "n"): y Resolved conflicted state of 'statusesC_text.txt'
Here we only had one file with one small conflict.
If we have 2 versions of a file, both with substantial changes, then the xxdiff display will be extremely colourful but very helpful.
In these cases it is often easier to start with one version of the file and manually re-apply the changes from the other version.
It might not be obvious how to do this and we may need to speak to the author of the other change to agree how to correctly combine the change.
Fortunately this situation should be very rare.
resolve
The fcm resolve
command can be used to resolve conflicts in
local/working copy files or directories.
A common way of using this command is:
fcm resolve --accept working <FILENAME>
cd ~/my_fcm_tutorial/specifics fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_resolve fcm bls [info] fcm:fcm_sp@78: 9 match(es) fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_conflict_tree@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_conflict_tree2@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_merge_custom@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_merge_custom2@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_propdel@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_propedit@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_propset_exe@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_propset_ign@78 fcm:fcm_sp/branches/dev/$LOGNAME/r36_branch_resolve@78 fcm merge fcm:fcm_sp_br/dev/$LOGNAME/branch_conflict_tree Eligible merge(s) from /specifics/branches/dev/$LOGNAME/r36_branch_conflict_tree@78: 46 45 Enter a revision (or just press <return> for "46"): -------------------------------------------------------------------------------- Merge: /specifics/branches/dev/$LOGNAME/r36_branch_conflict_tree@46 c.f.: /specifics/trunk@643 -------------------------------------------------------------------------dry-run --- Merging r44 through r46 into '.': C lib/utility A lib/utility/tool_list.txt D tree_conflict.txt Summary of conflicts: Tree conflicts: 1 -------------------------------------------------------------------------dry-run Would you like to go ahead with the merge? Enter "y" or "n" (or just press <return> for "n"): y Merge succeeded. --------------------------------------------------------------------------actual --- Recording mergeinfo for merge of r42 through r43 into '.': U . --- Merging r44 through r46 into '.': C lib/utility A lib/utility/tool_list.txt D tree_conflict.txt --- Recording mergeinfo for merge of r44 through r46 into '.': U lib/utility/tool_list.txt G . Summary of conflicts: Tree conflicts: 1 --------------------------------------------------------------------------actual fcm st M . C lib/utility > local dir obstruction, incoming dir add upon merge M lib/utility/tool_list.txt D tree_conflict.txt Summary of conflicts: Tree conflicts: 1 fcm resolve --accept working lib/utility Resolved conflicted state of 'lib/utility'
The conflict has been resolved.
We will use this command further in the conflicts section and scroll down to the tree conflict sub-section.
Tree conflicts
Tree conflict, which are otherwise known as a structural or filesystem-based conflicts.
These can be more complicated than text conflicts.
fcm st
returns the following when there is a tree conflict on the
repository, indicated by a "C" present in column 7 of the returned output:
C lib/utility/my_tools
fcm conflicts
should manually resolve the problem by prompting us
to choose a course of action.
We can either keep the file as it was before the merge (keeping the local copy),
or accept the external changes to the file.
FCM has issues when the same directory or file has been added to two separate branches. The problem can occur when merging two branches that both have the same directory or file added. E.g. JoeBloggs added lib/utility/my_tool to a branch and we also added the same directory or file. Assuming that both add exactly the same directories or files then running the following command in our local/working copy should get around this problem.
fcm resolve --accept working lib/utility/my_tools
As we used above in the resolve sub-section.
A common way to generate a tree conflict after a merge is when a file has been deleted or renamed on one branch, and modified on another. These are incompatible changes, therefore Subversion doesn't know which action to take. This is the cause of the tree conflict dilemma which the user must solve.
cd ~/my_fcm_tutorial/specifics fcm sw fcm:fcm_sp/branches/dev/${LOGNAME}/r36_branch_conflict_tree fcm up # The file tree_conflict.txt has been deleted from it. # Merge in branch_conflict_tree2 which has a modification to tree_conflict.txt
fcm merge fcm:fcm_sp_br/dev/$LOGNAME/branch_conflict_tree2
Accept the merge.
Eligible merge(s) from /specifics/branches/dev/$LOGNAME/r36_branch_conflict_tree2@78: 48
--------------------------------------------------------------------------------
Merge: /specifics/branches/dev/$LOGNAME/r36_branch_conflict_tree2@48
c.f.: /specifics/trunk@643
-------------------------------------------------------------------------dry-run
--- Merging r47 through r48 into '.':
C tree_conflict.txt
Summary of conflicts:
Tree conflicts: 1
-------------------------------------------------------------------------dry-run
Would you like to go ahead with the merge?
Enter "y" or "n" (or just press <return> for "n"): y
Merge succeeded.
--------------------------------------------------------------------------actual
--- Recording mergeinfo for merge of r44 through r46 into '.':
U .
--- Merging r47 through r48 into '.':
C tree_conflict.txt
--- Recording mergeinfo for merge of r47 through r48 into '.':
G .
Summary of conflicts:
Tree conflicts: 1
--------------------------------------------------------------------------actual
How can we try to resolve the conflict?
fcm conflicts
# choose to keep the local version or not.
[info] tree_conflict.txt: in tree conflict.
Locally: deleted.
Externally: edited.
Answer (y) to accept the local delete.
Answer (n) to keep the file.
Keep the local version?
Enter "y" or "n" (or just press <return> for "n") y
Resolved conflicted state of 'tree_conflict.txt'
In this example, to keep the file as it was before (in a deleted state), enter y.
Otherwise, to accept the merge branch version of the file (adding it with the edited changes), enter n.
fcm conflicts
does not cover tree conflicts on directories
because of the potential nesting of conflicts within the directories.
We have already covered an example of this above in the resolve sub-section.
Note, it can often be difficult to identify the problem and figure out the solution in the case of directory conflicts, and the easiest solution may be to try to resolve the discrepancy before the merge.
Use fcm st
to find out if the tree conflict has arisen from a
rename.
A rename can have occurred locally or externally.
An external rename would show up in fcm status
as an addition with history
(A with +): for example:
A + FILENAME
Now we can use fcm log -v <FILENAME>
to examine if this is
really just a rename then it will show up as FILENAME (from ORIGINAL_FILENAME).
Warning, local renames that have been committed won't show up in
fcm status
.
However, these can still be found using fcm log -v
for each
filename.
tree conflicts resolution list
Commands to use to help with resolving tree conflicts:fcm st fcm log -v <FILENAME> fcm resolve --accept working <FILENAME> fcm help <COMMAND>
local add, incoming add upon merge
- meaning: files or directories added with the same name independently
-
what keep local does: it uses rename to shuffle the old file
to a different name, copies the new file in, renames the new file to the
original name but with a temporary-style suffix (e.g. hello.py -> hello.py.xD4),and again renames the old file to the original name.
Then it runs
fcm resolve
. -
what discarding local does: it renames the old file to give it
a temporary-style suffix (e.g. hello.py -> hello.py.r6Ys), and copies the new
file into the original name.
Then it runs
fcm resolve
.
local edit, incoming delete upon merge (no renaming)
- meaning: file or directory modified on the branch locally, but deleted on the merge branch
- what keep local does: it just runs
fcm resolve
. - what discarding local does: it deletes the file or directory
and then runs
fcm resolve
.
local edit, incoming delete upon merge (renaming)
- meaning: file modified on branch locally, but renamed on merge branch
-
what keep local does: it copies over the renamed file, and
the common ancestor of the file on the branches, and uses them for a text
conflict style merge into the old (local) filename.
It then removes the renamed file and then runs
fcm resolve
. -
what discarding local does: it copies over the renamed file,
and the common ancestor of the file on the branches, and uses them for a text
conflict style merge into the new renamed file.
It then deletes the old file and then runs
fcm resolve
.
- meaning: same filename deleted both locally and externally
- for both: it just runs
fcm resolve
.
local delete, incoming delete upon merge (just external renaming)
- meaning: file deleted locally, but renamed externally
- what keep local does: it just runs
fcm resolve
. - what discarding local does: it just deletes the new renamed
file and then runs
fcm resolve
.
local delete, incoming delete upon merge (just local renaming)
- meaning: file renamed locally, but deleted externally
- what keep local does: it just runs
fcm resolve
. - what discarding local does: it deletes the local renamed file
and then runs
fcm resolve
.
local delete, incoming delete upon merge (local renaming AND external renaming)
- meaning: same file renamed locally AND externally, to two different names.
-
what keep local does: it copies in the external file and
the common ancestor file to construct a text-style merge using xxdiff into the
locally-renamed filename.
It then removes the external rename and then runs
fcm resolve
. -
what discarding local does: it copies in the external file and
the common ancestor file to construct a text-style merge using xxdiff into the
externally-renamed filename.
It then removes the local rename and then runs
fcm resolve
.
local missing, incoming edit upon merge (no renaming)
- meaning: locally deleted file, add newer file from merge branch?
- what keep local does: it just runs
fcm resolve
. - what discarding local does: it copies in the external file
using its URL and then runs
fcm resolve
.
local missing, incoming edit upon merge (renaming)
- meaning: locally renamed file, but external changes to the old filename
- what keep local does: it copies in the external file and the common ancestor to construct a text-style merge using xxdiff, into the locally-renamed filename.
local missing, incoming edit upon merge (renaming)
- meaning: locally renamed file, but external changes to the old filename
-
what keep local does: it copies in the external file and
the common ancestor to construct a text-style merge using xxdiff, into the
locally-renamed filename.
It then runs
fcm resolve
. -
what discarding local does: it copies in the external file and
the common ancestor to construct a text-style merge using xxdiff, into the
original filename.
It then deletes the locally-renamed file and adds the original filename, then it runs
fcm resolve
.
A final resort or a simpler solution: checkout a new working/local copy of the trunk/branch or create a new branch from the trunk/branch and apply your changes using best working practices and only making one or a few changes at a time, committing the changes to your branch and merging to the trunk only a few changes at a time.
cherry pick
There is no support for cherry picking from a branch in FCM.
If you decide to try to do this then there will be no user support.
Congratulations you have completed the FCM tutorial!
Don't forget to remove the repository if it is not needed anymore or if you
wish to do the repository again in the future.
rm -rf ~/fcm_tutorial; rm -rf ~my_fcm_tutorial
WARNING: this is a draft document it is under review awaiting approval and can be removed at any time
This document is released under the British Open Government Licence.