This describes how to synchronize org files using the Unison file synchronizer, as well as how to configure it to use an external tool to merge conflicting edits.
Unison is a file synchronizer, thus it may be used to synchronize org files. To
configure Unison, one uses a profile which states where the things to
synchronize are as well as some options. Assuming I want to synchronize the
/Users/schmitta/dir2, the profile would
look like this
root = /Users/schmitta/dir1 root = /Users/schmitta/dir2
In most cases Unison will be used with a remote machine. The local machine is
called the client and the remote one the server. For such remote
unison binary must be installed in the server as
well. The simplest way to connect to the machine is using ssh. One should check
that unison can be found there by doing
ssh user@remote unison -version. If
unison cannot be found in the path, one may set the
servercmd option as
indicated in the next example.
(Please see the manual section on roots for further details.)
root = /Users/schmitta/dir1 root = ssh://user@remote/relative/path/to/dir2 servercmd = /usr/bin/unison
As Unison works on the level of files, it will trigger a conflict if both files have changed since the last synchronization. In that case one can only choose which file to keep, which is not satisfactory. Unison offers the possibility to use external tools to merge the files. There is an extensive manual section regarding this, we'll just describe how to use emacs and ediff to do it.
For better merging, we will ask unison to keep the last synchronized version of
every org file on the client; this way we can use ediff with ancestor. These
currentbackup files may live alongside the synchronized files (with names of
.bak.version.name, which is configurable) or in a central location.
Here is the modified configuration file.
root = /Users/schmitta/dir1 root = ssh://user@remote/relative/path/to/dir2 servercmd = /usr/bin/unison backupcurrent = Name *.org backuplocation = local maxbackups = 0 merge = Name *.org -> emacsclient -c --eval '(ediff-merge-files-with-ancestor "CURRENT1" "CURRENT2" "CURRENTARCH" nil "NEW")'
backupcurrent option tells unison to keep a backup of the last
synchronized version of every file with an
org extension. The location of the
backup should be local (alongside the file). Finally, no other backup should be
Next follows the merge command. For every org file in conflict, use the command
that launches a new emacs frame calling the ediff with ancestor function. The
CURRENTARCH strings are replaced with the file
from the first root, the file from the second root, and the last synchronized
NEW file is where Unison expects the file to be saved (which will
be done by the ediff session).
Thus, when an org file has been modified on both hosts, an ediff session will be launched in a new frame. Closing the frame will make Unison commit the merge (it waits until the command has finished).
If one does not want to use backups, it's possible to use the simpler ediff (without ancestor) command as follows.
root = /Users/schmitta/dir1 root = ssh://user@remote/relative/path/to/dir2 servercmd = /usr/bin/unison merge = Name *.org -> emacsclient -c --eval '(ediff-merge-files "CURRENT1" "CURRENT2" nil "NEW")'