In which I move my version control from ComponentSoftware’s CS-RCS Pro to Git while preserving commit history.
[If you don’t want the back story, click here for the instructions!]
OK, so having watched the video I linked to earlier, I thought I’d move some of my old projects to Git.
I picked one at random, and went looking for tools.
I’m hampered a little by the fact that all my old projects used ComponentSoftware’s “CS-RCS Pro”.
Why did you choose CS-RCS Pro?
A couple of really good reasons:
- It works on Windows
- It integrates moderately well with Visual Studio through the VSS functionality
- It’s compatible with GNU RCS, which I had some familiarity with
- It was free if you’re the only dev on your projects
But you know who doesn’t use CS-RCS Pro any more?
That’s right, ComponentSoftware.
It’s a dead platform, unsupported, unpatched, and belongs off my systems.
So why’s it still there?
One simple reason – if I move off the platform, I face the usual choice when migrating from one version control system to another:
- Carry all my history, so that I can review earlier versions of the code (for instance, when someone says they’ve got a new bug that never happened in the old version, or when I find a reversion, or when there’s a fix needed in one area of the code tree that I know I already made in a different area and just need to copy)
- Lose all the history by starting fresh with the working copy of the source code
The second option seems a bit of a waste to me.
OK, so yes, technically I could mix the two modes, by using CS-RCS Pro to browse the ancient history when I need to, and Git to browse recent history, after starting Git from a clean working folder. But I could see a couple of problems:
- Of course the bug I’m looking through history for is going to be across the two source control packages
- It would mean I still have CS-RCS Pro sitting around installed, unpatched and likely vulnerable, on one of my dev systems
So, really, I wanted to make sure that I could move my files, history and all.
What stopped you?
I really didn’t have a good way to do it.
Clearly, any version control system can be moved to any other version control system by the simple expedient of:
- For each change X:
- Set the system date to X’s date
- Fetch the old source control’s files from X into the workspace
- Commit changes to the new source control, with any comments from X
- Next change
But, as you can imagine, that’s really long-winded and manual. That should be automatable.
In fact, given the shared APIs of VSS-compatible source control services, I’m truly surprised that nobody has yet written a tool to do basically this task. I’d get on it myself, but I have other things to do. Maybe someone will write a “VSS2Git” or “VSS2VSS” toolkit to do just this.
There is a format for creating a single-file copy of a Git repository, which Git can process using the command “git fast-import”. So all I have to find is a tool that goes from a CS-RCS repository to the fast-import file format.
Nobody uses CS-RCS Pro
So, clearly there’s no tool to go from CS-RCS Pro to Git. There’s a tool to go from CS-RCS Pro to CVS, or there was, but that was on the now-defunct CS-RCS web site.
But… Remember I said that it’s compatible with GNU RCS.
And there’s scripts to go from GNU RCS to Git.
What you waiting for? Do it!
OK, so the script for this is written in Ruby, and as I read it, there seemed to be a few things that made it look like it might be for Linux only.
I really wasn’t interested in making a Linux VM (easy though that may be) just so I could convert my data.
So why are you writing this?
Everything changed with the arrival of the recent Windows 10 Anniversary Update, because along with it came a new component.
Bash on Ubuntu on Windows.
It’s like a Linux VM, without needing a VM, without having to install Linux, and it works really well.
With this, I could get all the tools I needed – GNU RCS, in case I needed it; Ruby; Git command line – and then I could try this out for myself.
Of course, I wouldn’t be publishing this if it wasn’t somewhat successful. But there are some caveats, OK?
Here’s the caveats
I’ve tried this a few times, on ONE of my own projects. This isn’t robustly tested, so if something goes all wrong, please by all means share, and people who are interested (maybe me) will probably offer suggestions, some of them useful. I’m not remotely warrantying this or suggesting it’s perfect. It may wipe your development history out of your one and only copy of version control… so don’t do it on your one and only copy. Make a backup first.
GNU RCS likes to store files in one of two places – either in the same directory as the working files, but with a “,v” pseudo-extension added to the filename, or in a sub-directory off each working folder, called “RCS” and with the same “,v” extension on the files. If you did either of these things, there’s no surprises. But…
CS-RCS Pro doesn’t do this. It has a separate RCS Repository Root. I put mine in C:\RCS, but you may have yours somewhere else. Underneath that RCS Repository Root is a full tree of the drives you’ve used CS-RCS to store (without the “:”), and a tree under that. I really hope you didn’t embed anything too deep, because that might bode ill.
Initially, this seemed like a bad thing, but because you don’t actually need the working files for this task, you can pretend that the RCS Repository is actually your working space.
Maybe this is obvious, but it took me a moment of thinking to decide I didn’t have to move files into RCS sub-folders of my working directories.
Make this a “flag day”. After you do this conversion, never use CS-RCS Pro again. It was good, and it did the job, and it’s now buried in the garden next to Old Yeller. Do not sprinkle the zombification water on that hallowed ground to revive it.
This also means you MUST check in all your code before converting, because checking it in afterwards will be … difficult.
Enough already, how do we do this?
Assumption: You have Windows 10.
- Install Windows 10 Anniversary Update – this is really easy, it’s an update, you’ve probably been offered it already, and you may even have installed it. This is how you’ll know you have it:
- Install Bash on Ubuntu on Windows – everyone else has written an article on how to do this, so here’s a link (I was going to link to the PC World article, but the full-page ad that popped up and obscured the screen, without letting me click the “no thanks” button persuaded me otherwise).
- Run the following commands in the bash shell:
sudo apt-get update
sudo apt-get install git
sudo apt-get install ruby
- [Optional] Run “sudo apt-get instal rcs”, if you want to use the GNU RCS toolset to play with your original source control tree. Not sure I’d recommend doing too much of that.
- Change directory in the bash shell to a new, blank workspace folder you can afford to mess around in.
- Now a long bash command, but this really simply downloads the file containing rcs-fast-export:
curl http://git.oblomov.eu/rcs-fast-export/blob_plain/c8a2bd6edbb21c1bfaf269ad1ec0e82af72c911a:/rcs-fast-export.rb -o rcs-fast-export.rb
- Make it executable with the command “chmod +x rcs-fast-export.rb”
- Git uses email addresses, rather than owner names, and it insists on them having angle brackets. If your username in CS-RCS Pro was “bob”, and your email address is “firstname.lastname@example.org”, create an authors file with a bash command like this:
echo “bob=Kate Smith <email@example.com>” > AuthorsFile
- Now do the actual creation of the file to be imported, with this bash command:
./rcs-fast-export.rb -A AuthorsFile /mnt/c/RCS/…path-to-project… > project-name.gitexport
[Note a couple of things here – starting with “./”, because that isn’t automatically in the PATH in Linux. Your Windows files are logically mounted in drives under /mnt, so C:\RCS is in /mnt/c/RCS. Case is important. Your “…path-to-project…” probably starts with “c/”, so that’s going to look like “/mnt/c/RCS/c/…” which might look awkward, but is correct. Use TAB-completion on folder names to help you.]
- Read the errors and correct any interesting ones.
- Now import the file into Git. We’re going to initialise a Git repository in the “.git” folder under the current folder, import the file, reset the head, and finally checkout all the files into the “master” branch under the current directory “.”. These are the bash commands to do this:
git fast-import < project-name.gitexport
git checkout master .
- If you’re using Visual Studio and want to connect to this Git repository, remember that your Linux home directory sits under “%userprofile%\appdata\local\lxss\home”
This might look like a lot of instructions, but I mostly just wanted to be clear. This is really quick work. If you screw up after the “git init” command, simply “rm –rf .git” to remove the new repository.