2022-02-13: New version
This release fixes a bug that causes diff dialogs to crash.
Updates about Visual Git are posted here. RSS eventually.
This release fixes a bug that causes diff dialogs to crash.
I've released a new version with support for cherry picking and some other improvements. Give it a shot and let me know how it goes.
After mulling it, I'm making the source code to Visual Git available. Currently, it's GPLv2 (the same as libgit2, my big copylefted-but-with-linking-exception dependency), because copyleft does make sense for applications to me. GPL isn't my favourite license though, so I may reconsider and relicense. Enjoy!
I'm finally ready to release Visual Git (with actual binaries, that you can go out and download) to the public. If you don't know what it is, it's both a Git porcelain (operating standalone) and an IDE extension (using a 90s era source control integration standard that MS and non-MS IDEs used... and still use to this day). It's been the culmination of on-off effort starting from the end of June until now. During that time, I've managed to touch a lot of different things, from backporting things to older Windows APIs, to working with obscure yet documented Visual Studio APIs, and ended up making something I think might be useful to people. I'll recount the highlight reel of the difficulties I encountered, as well as why I initially wrote it in the first place.
I initially wrote it half to satisify some lingering desire, half joke. Initially I had wanted something better for source control with my retro projects (poking old Windows stuff is a hobby of mine), and thought the juxtaposition of Visual Basic and Git would be funny. However, I had realized this is actually useful. There's almost certainly a lot of Visual Basic et al in the wild that could do with something better than SourceSafe. As much fun it can be to develop on an old system, I don't think anyone wants to go back to the bear skins and stone knives of centralized version control they can't effectively use from a modern system.
First, I actually had to be able to even use Git from the older Windows (2000, because it's a reasonable subset of Win32, and a good vintage) and Visual Studio (the SCC API is flexible enough to support pretty much every 32-bit version) I wanted to target. The obvious choice is libgit2, which is written in mostly portable C89, and doesn't need another Git implementation. I had also chosen Visual C++ 6 as the toolchain, partly to experience what it'd be like to build with it (it's the gcc 2.95 of Windows, after all), partly because it generates small low-dependency binaries, partly in case I managed to get it all building on Alpha (One day...). No problem, CMake only removed support for that relatively recently (so I could use 3.5), and there was no trouble with the CMakeLists in the dependencies with that version. However, I had to clean up some
long long and newer Windows API usage (usually related to symlinks). I had also needed to build OpenSSL, zlib, and libssh2. Keen readers will also note that I didn't strictly need OpenSSL because libgit2 can use WinHTTP and libssh2 can use BCrypt. However, the former limits you to whatever TLS the host Windows supports, and the latter requires Vista. Using OpenSSL would allow TLSv1.3 and SSH on older systems. (Anyways, my changes are all available from GitHub.)
The next thing to work with was the old Visual Studio source control plugin API. It slightly railroads you into the centralized VCS model by exposing a fixed set of functionality, and that functionality didn't map too well to Git. For example, the API assumes a check-out, then check-in model, but with Git, checking out is a completely different operation, and you can commit even if others have a copy. I had basically just mapped check-out to a nop, but had to implement it as a flag anyways because some IDEs dependend on the being able to query if a file is checked out before it can be committed or even edited. Other than that, the mapping of Git and SCC actions was surprisingly smooth. The rest of Git functionality could be implemented via shelling out to a new interface.
The other struggle with the SCC API is that not many people had implemented it, so although documentation existed, there wasn't a lot to rely on if something went wrong other than than old MSDN forum posts of souls trying to implement said API. I had ran into some confusing issues. One such issue was Visual C++ leaving the pointer to the previously initialized instance when calling
SccInitialize (since the API can have multiple handles for re-entrancy with multiple projects) to a new instance, where it should pass the handle to the allocated block for the new instance. This made me falsely believe it was a singleton. This confused me enough I tracked down the Microsoft employee who was answering those questions on the MSDN forum, who had conveniently wrote the post making me think this venture was even possible. I managed to figure it out on my own anyways. Sorry Alin!
There was also some scope creep along the way. Initially, I was only going to do a source control provider for integration into IDEs. However, to expose functionality that only exists in Git that isn't exposed via SCC's fixed functionality, I had to build a UI for it (This was exposed by the
SccRunScc API.). Then from there, why not display i.e. Git status? I eventually realized I had a Git porcelain, and decided to run on both the SCC plugin and the standalone porcelain. The porcelain part would make it without an old IDE, even on modern Windows.
I think that drive for the porcelain being useful on its own led me to have some ideals for the project. My two hobby horses were making good use of the GUI (by using little things like icons to show differences), and cleaning up the terminology used by Git. For the former, I wanted to actually take advantage of the metaphors a GUI can enable, and that the command line isn't good at. Of course, there's definitely stuff that the Git default command-line porcelain can do that Visual Git can't, a lot isn't implemented yet - not because a GUI isn't capable of doing it well. For the latter, overloaded and confusing terminology is one of the reasons why Git tends to be inscrutable to many users. The entire stage/index saga is one sordid example. It's why I try to pick sometihng I find is more obvious, make sure other terms don't tend to also describe it, and stick with it; for example, I follow in calling it the stage.
Another thing I'm working is documentation. While I'm not sure if it's strictly necessary (much of the UI should come off as intuitive, and what doesn't should be safe to experiment with), I think it'll be useful for explaining the SCC to Git command mapping, due to the aforementioned checkout issues. I'm experimenting with Halibut, but I'm open to alternatives. (The website is the other thorn in my side; the entire static site generator field is so greasy and overwhelming I resorted to writing HTML and M4 by hand. M4! What's wrong with me?)
Anyways, I plan to eventually open source it. There's a lot of stuff in the code I want to clean up (things like setting up the build environment, some of the uglier hacks, etc.) before I feel comfortable releasing it to the public; when I do, I'll be sure to let people know. After all, I don't want to let it sit. It took me a while to feel confident enough to release public binaries! Of course, as previously mentioned, the things I've needed to change are in branches on GitHub. In the meantime, I'd love to hear your feedback. I'm also running a survey about what'd people like to see in Visual Git as well, out of curiosity and gauging interest. I'd like to hear from you if you're using it, and what your plans for it are! If I hear back from people, I'll probably get around to making a channel somewhere for discussions.
Oh, and of course, you can get Visual Git by clicking right here. ~cb