Since I spent so many hours on this, I figured I'll post this to remember...
When copying SPFiles from one doc library to another, a few things to keep in mind:
- SPFileVersion will not let you get a reference to the SPFile (per MSDN) so don't do this: SPWeb.GetFile(SPFileVersion.Url) because SPFile.Item will be null
- SPFileVersionCollection (SPFile.Versions) is not in sync with SPListItemVersionCollection. SPFile.Versions actually does NOT return the current version. So, iterate through all SPFileVersions and use SPFile.Versions.GetVersionFromLabel(SPListItemVersion.VersionLabel)
- To keep the check in comments with each version, use the following method to add a file to the target library: SPList.RootFolder.Files.Add(url,bytes,true,SPFileVersion.CheckInComments,false)
- Iterate through versions via a SortedDictionary by Created date property -- the goal is to use SPListItemVersion information to update the newly created SPFile meta data.
- SPFile.Item.Update() will create a new version; UpdateOverwriteVersion() will not; use the latter with SPFileVersions; use the former when adding a new SPListItem, to set values and incremenet versions.
- Upload the current version of SPFile outside the SPListItemVersions loop
- Be mindful that SPListItemVersion returns Modified and Created values as non-local time, so convert it.
Consider disabling item events during copy.
A good reference:
http://www.k2distillery.com/2007/10/copy-version-history-with_5.html