Wednesday, August 19, 2015

Git 2.5 handles multiple working copies, and its available now for Windows

Yesterday, I posted about tricks and scripts to support multiple working copies all using the same repository. Later in the day I realized Git for Windows 2.5 had been released. Now you can uninstall any previous distribution of Git, and install this. Any thing like GitExtensions or SourceTree will use it if you add Git to your path during installation. Then you can use the nifty worktree command to create new working copies that all point back to a single repository on your machine. This means native support for multiple working copies; no symbolic links necesssary.

Tuesday, August 18, 2015

A single git repository with multiple working copies on Windows

A project at my company recently transitioned from ClearCase to Git. The codebase is large and monolithic and as such a bare clone of the repository with relatively few commits is over 20 GB not counting any working copy files. Many developers have several clones of the repo to allow working on different releases without having to switch branches and rebuild all the code which is time expensive on this large codebase. This means having 3 or more copies of a growing 20 GB git repo.

Why is it necessary to have duplicates of the data in a repository on a given machine? Its not. Git has a user contributed script to create symbolic links to an existing git repository for a new working copy called "git-new-workdir". (Git 2.5.0 will have this feature baked in, with the worktree command EDIT: Apparently it has now been released for Windows.) When I attempted to use this script from git bash on Windows, however, it created a copy of the working copy instead of referencing it with symbolic links as intended.

Eventually, I found a branch of it for Windows that uses mklink to create the symbolic links. I put the script in the same directory as my working copies so that I can navigate in git bash to that directory and run it with "bash git-new-workdir-win". It expects the path to the original repository (on your machine), the path to the desired new working directory, and optionally the branch to checkout.

Before I found this script, I was able to get the same functionality by manually creating the links following a guide I found for getting this functionality on Windows XP. Note that the script yields slightly different results that are probably slightly better than this manual process, although either solution works. Specifically, the script does not symbolically link the logs directory but does symbolically link a few of the files such as "config" found in the root .git directory.

If you have existing working copies you want to convert to using symbolic links without having to recheck out code, you should be able to retain them and use the manual method to overwrite the directories within the .git directory, or run the script to create a new working copy, then overwrite the directories and files in your existing .git with just the ones that are symbolic links in the new working copy. I'll take this opportunity to give a shout out to Link Shell Extension, which is a great shell extension for creating symbolic links, hard links, etc within Windows Explorer without having to use mklink through the command line. This extension will make it obvious which directory elements are symbolic links in Windows Explorer. Also make sure you've pushed any commits/branches you want to keep before overwriting things inside your .git.

Since symbolic links will fail if the source they are pointing at are removed, I first moved an existing repository to a safe place on my machine, then replaced all my existing repositories/working copies with links to this repository using the mechanisms mentioned. This mitigates the risk of accidentally deleting the source of your symbolic links if you were to use an existing working copy's repository then some time later remove it when it is no longer needed. If you want to start with a brand new repository instead, you can pull down just the .git directory without creating a working copy using git clone --bare.



tl;dr: Get this script and run it