Fossil: The "fossil patch" command

Fossil SCM

The "fossil patch" command is designed to transfer uncommitted changes from one check-out to another, including transfering those changes to other machines.

For example, if you are working on a Windows desktop and you want to test your changes on a Linux server before you commit, you can use the "fossil patch push" command to make a copy of all your changes on the remote Linux server:

fossil patch push linuxserver:/path/to/checkout

In the previous "linuxserver" is the name of the remote machine and "/path/to/checkout" is an existing checkout directory for the same project on the remote machine.

The "fossil patch push" command works by first creating a patch file, then transfering that patch file to the remote machine using "ssh", then applying the patch. If you do not have ssh available, you can break these steps apart as follows:

  1. On the local machine: fossil patch create mypatch.patch
  2. Move "mypatch.patch" to the remote machine.
  3. On the remote machine: fossil patch apply mypatch.patch

Step 2 can be accomplished by a variety of means including posting the mypatch.patch file on chat or sending it as an email attachment.

Setup

The "fossil patch push" and "fossil patch pull" commands will only work if you have "ssh" available on the local machine and if "fossil" is on the default PATH on the remote machine.

To check if Fossil is installed correctly on the remote, try a command like this:

ssh -T remote "fossil version"

If the command above shows a recent version of Fossil, then you should be set to go. If you get "fossil not found", or if the version shown is too old, put a newer fossil executable on the default PATH. The default PATH can be shown using:

ssh -T remote 'echo $PATH'

Custom PATH Caveat

On Unix-like systems, the init script for the user's login shell (e.g. ~/.profile or ~/.bash_profile) may be configured to not do anything when running under a non-interactive shell. Thus a fossil binary installed to a custom directory might not be found. To allow the patch command to use a fossil binary installed in a directory which is normally added to the PATH via the interactive shell's init script, it may be useful to disable that check. For example, Ubuntu-derived systems sometimes start their default .bashrc with something like:

# If not running interactively, don't do anything:
[ -z "$PS1" ] && return
# Or:
case $- in
    *i*) ;;
    *) return;;
esac

Commenting out that check will allow the patch command to run, for example, ~/bin/fossil if ~/bin is added to the PATH via the init script. To disable that check only when the shell is not running over an SSH connection, something like the following should suffice:

if [ -z "$SSH_CONNECTION" ]; then
  # ... the is-interactive check goes here ...
fi

Implementation Details

The "fossil patch create" command records all of the local, uncommitted changes in an SQLite database file. If the argument to "fossil patch create" is a filename, then the patch-file database is written into that file. If the argument is "-" then the database is written on standard output.

The "fossil patch apply" command reads the database that is the patch file and applies it to the local check-out. If a filename is given as an argument, then the database is read from that file. If the argument is "-" then the database is read from standard input.

Hence the command:

fossil patch push remote:projectA

Is equivalent to:

fossil patch create - | ssh -T remote 'cd projectA;fossil patch apply -'

Likewise, a command like this:

fossil patch pull remote:projB

Could be entered like this:

ssh -T remote 'cd projB;fossil patch create -' | fossil patch apply -

The "fossil patch view" command just opens the database file and prints a summary of its contents on standard output.