-
Notifications
You must be signed in to change notification settings - Fork 3
Home
I don’t work with VSS anymore, so it’s highly unlikely that I will be developing this any further. If you need any changes, feel free to fork.
This script implements bi-directional exchange of simple changes between Git and VSS. It depends on the logging feature of VSS, which is the only way to quickly find what changed without scanning the whole repository. Unfortunately, it is not very reliable even by VSS standards.
The first step is to ensure that logging is enabled in VSS, and then create a Git mirror of the VSS repository. This operation can be done by first converting it to svn via vss2svn, or by any other available means.
The next step is to create a bare repository (henceforth referred to as the base repository) with the necessary branches, and initialize git-vss using the following command from within it:
git vss --init [--no-mappings] [--no-fetch] \ branchname vss_repo log_path log_offset < mappings.txt
Here branchname specifies the Git branch, vss_repo is the path to the VSS repository, log_path names the VSS log file, and log_offset specifies an offset where to start reading it. This offset should generally be the size of the file at the moment when the initial snapshot was taken.
(It is also possible to initialize a branch by importing a check-out. To do this, use --import=path
instead of --init
.)
The base repository is expected to be located on a network share and used by all git-vss users that connect to the same VSS repository as a coordination point. The script maintains it as a mirror of the VSS tree, except that all commits submitted via git-vss are directly pushed there so that all meta-data is preserved intact.
The mappings specify how paths in VSS map to paths in the Git repository, using the following format:
# Comment /vss/path/one = /git/path /vss/path/two = /git /vss/path/two/junk = IGNORE ...
During processing the script uses the longest matching prefix.
In order to create a working copy, clone the base repository and run the following command:
git vss --connect <path-to-the-base-repo>
It is possible to import a mapping of VSS logins to Git-style authors and e-mails, and a list of file names, by running this command in the central bare repository:
--load [--authors=file] [--filenames=file]
The file name list is used to canonify the case in order to work around some issues in past versions of Git regarding filename case on case-insensitive filesystems. This feature may be obsolete by now.
In order to import changes from VSS to Git, use the following command in your working copy:
git vss [--new-head] [--rebase] branchname
The branch name must match one of the names used with the —init command. The rebase flag makes this command behave like git svn rebase
instead of git svn fetch
.
The new-head flag must be used to override the internal integrity check after manually fixing the branch in the base repository. This may be necessary if the script fails to handle some of the more complex operations in VSS.
The script should work reliably with simple file changes, additions, and removals; file renames are tricky due to numerous bugs and misfeatures of VSS. Folder moves and archive restores don’t work at all.
Your changes can be uploaded to VSS by running the following command in your working copy:
git vss --commit [--squash=title[:]] branchname
This command internally performs the following steps:
- Determines the set of files that you changed and locks them in VSS (i.e. does a check out).
- Performs a fetch & rebase.
- Commits your changes one by one to VSS.
- Pushes your branch to the base repository and records it as the new head.
- Removes locks created by the first step.
If the squash flag is used, the command commits all your changes to VSS at once. However, on the git side it uses merge instead of rebase, so the base repository preserves full history. If the title is terminated with a colon, the VSS commit comments also include the messages from all the merged Git commits.
It is possible to invoke only the first two, or the last step using:
git vss --checkout branchname git vss --undo-checkouts [branchname]
The set of current check-outs is maintained in .git/vss-checkouts, so it is easy to undo them even if the script crashes.
The commit code can handle adding and changing files. Deletion wasn’t implemented due to lack of need (it is also arguably more dangerous in case of a bug).
TODO
Usage: git-vss [-h|--help] [--root=GIT_repository] parameters... Update Git from VSS: [--new-head] [--checkout] [--rebase] branchname Commit changes from Git into VSS: --commit [--squash=title[:]] branchname Undo previous checkouts: --undo-checkouts [branchname] Repin commits to the specified branch: --repin branchname commit commit... Initialize repository: --connect base_path (--init|--import=path) [--no-mappings] [--no-fetch] branchname vss_repo log_path log_offset < mappings (--load|--dump) [--authors=file] [--filenames=file] Canonify newly-added file names in the index: --sanitize-adds