Are there suitable versioning systems for Mathematica notebooks?
First, if you want to have a team working on Mathematica code, then you really should do it properly and use Wolfram Workbench. As pointed out by Leonid, notebooks are not the right tool for software development.
This said, I have used version control (git) with a notebook and successfully merged versions. To do it, I minimized the amount of metadata in the notebook by:
- Turning off Notebook History (and clearing any existing history using the dialog)
- Turning off the Notebook Cache (in the option inspector).
You can turn off both notebook options with with the single command
SetOptions[InputNotebook[],
PrivateNotebookOptions -> {"FileOutlineCache" -> False},
TrackCellChangeTimes -> False]
but clearing the existing notebook history (removing all of the CellChangeTimes
cell options) is easiest using the provided dialog.
Outputs can be long and messy and normally don't want to be tracked by your VCS. Some input/ouput combinations I did want to keep, so I set the output cell option GeneratedCell->False
and then both cells' options to make them non-deletable and non-editable. The rest of the output cells were removed using the Delete All Output menu option.
Finally, keep your notebook(s) well organised with sections and subsections so that work and changes are clearly localised, which will make possible merges easier.
If you plan to start a project with several developers involved, I would not base it on notebooks, because, as was mentioned by others, notebooks contain too much metadata. If you open a notebook file in a text editor, you will see that the actual code in the input cells only occupies a small fraction of the total file's size.
Besides, notebooks are aimed at a very different goal: explorations, interactive visualizations, and perhaps rapid prototyping. They are not aimed at structuring and maintaining code bases, at least not without some extra framework built on top of the core notebook interface.
I would definitely recommend the toolchain containing Wolfram Workbench (which is based on Eclipse and integrates with CVS and SVN), Mathematica packages,and the MUnit package for unit tests. Packages contain just code, are in plain ASCII files, and are well-suited for versioning. Developers can still use notebooks for interactive development, but I would not do shared work with notebooks. I would rather use them in two other capacities where they shine:
- Exploration and prototyping medium for individual developers (don't have to be shared)
- A medium of communication: one developer can create a notebook with illustrations, and send to others or commit that under his / her own sub-project. Others can use that to quickly see things, but would not modify it.
Of course, I don't mean to suggest that notebooks should never be shared and jointly modified, but if you reduce that to a minimum, you will avoid most of the merging problems involving them.
The bottom line of my message here is that code should be separated from the environment which has nothing to do with the problem that the code solves directly. The less metadata you will have hanging around the better it will be, because this metadata creates serious mental overhead for the developers. For any project except most trivial ones, this overhead will actually be much larger than the one associated with learning and using Workbench and related tools. And, the Workbench is integrated with Mathematica /FrontEnd sufficiently tightly that you don't lose the advantages notebooks give you - interactivity, rapid prototyping, etc.
I lack the reputation to comment on a different answer so I must write my own answer (how perverse!).
Let me add to what simon wrote.
First, there need to be quotes around "TrackCellChangeTimes"
in the code he wrote here or else it enters the Notebook's options as something like CellContext`TrackCellChangeTimes
.
Second, it is possible to programmatically clear the CellChangeTimes
from a notebook. Here is one approach:
CleanNotebook[nb_NotebookObject] := Module[{}, SetOptions[nb, PrivateNotebookOptions -> {"FileOutlineCache" -> False}, "TrackCellChangeTimes" -> False]; SetSelectedNotebook[nb]; SelectionMove[nb, All, Notebook]; FrontEndExecute[{FrontEnd`RemoveOptions[FrontEnd`SelectionObject, "CellChangeTimes"]}] ]
The last three commands come from inspecting the system file ./SystemFiles/FrontEnd/SystemResources/HistoryOverview.nb
in the Mma distribution; that is the code for the palette which lets you inspect the CellChangeTimes.