Git Extensions runs on Linux now. It’s the Windows build, under Wine, with about fifty patches and one script.

curl -fsSL https://raw.githubusercontent.com/craig-b/gitextensions/wine-support/eng/wine/install.sh | sh

That’s the whole install. Type gitext-wine in a repository, or find Git Extensions in your application menu, and the browse window opens on it.

Why a fork

The stock build almost works. It gets as far as the main window, and then every time that window gains focus you get the bug-report dialog, because Wine’s taskbar doesn’t implement jump lists and the app asks for one on every activation. That fix is one of about fifty patches on the wine-support branch of my fork.

Some are Wine gaps worked around in code: the dashboard’s recent-repository tiles don’t respond to clicks because Wine’s list view has no tile mode and never sends the click notification; the Console tab shows a stale copy of the previous tab after you switch windows, because a child window from another process gets no back buffer; “Open with” and “Copy path” hand out Windows paths to a desktop that wants Linux ones. Some are quality of life that Windows users wouldn’t notice: process output that was unreadable in dark mode, a diff margin sized from the wrong font, a Linux terminal on the Tools menu instead of PuTTY. And some are about speed, which is a longer story and its own post. The short version: under Wine, starting git.exe costs about a third of a second, and Git Extensions starts git once or more per click. So the fork doesn’t start git.exe. It runs your Linux git through a small daemon instead, and everything downstream of that decision turns out to be an improvement.

What you need

Wine 10 or later. curl or wget, unzip or bsdtar, tar, sha256sum, and fontconfig, all of which you almost certainly have. Nothing needs root. If you want the Git GUI and GitK entries on the Tools menu to work, install Tk (git lists it as an optional dependency). A monospace font called Hack is nice to have, for reasons the next section gets to, but DejaVu Sans Mono will do.

You don’t need a Windows git or a .NET SDK. Everything comes from the release: a portable app archive built on Linux, and a tarball of everything that runs on the Linux side.

What the script does

It finds the latest release, downloads the two archives, checks them against the published checksums, and unpacks them under ~/.local/opt. Your settings and window positions live in that directory too and survive a re-run.

Then it builds a Wine prefix, and this is where it earns its keep, because Wine’s default font setup is wrong for this app in three separate ways. Every Windows process enumerates every font on your system at startup, so the script gives Wine a short list. The app’s UI font is Wine’s Tahoma, which lacks the arrow glyphs branch labels use, so the script tells Wine where to borrow them from. And the app’s default console and diff font is Consolas, which Wine substitutes with something proportional, and a terminal drawn in a proportional font looks like it’s been through a mangle. The script substitutes Hack when you have it, because Hack has the glyphs shell prompts draw their branch symbol with, and DejaVu Sans Mono otherwise.

The .NET desktop runtime is unpacked from Microsoft’s zip straight into the prefix’s Program Files\dotnet. No installer runs under Wine, and no Mono or Gecko prompt appears.

Last, a symlink in ~/.local/bin, a menu entry, and the icons in the hicolor sizes.

What it’s like to use

Git is your git. Every git call the app makes goes over a socket to a daemon on the Linux side, which runs your Linux git in your environment. So your global config applies, your identity, your credential helpers, your SSH keys and known hosts, your hooks, your LFS. Fetch and push work on the first try because nothing about credentials changed.

If your Linux git config already names a merge and diff tool, that’s what you get. Check merge.guitool and diff.guitool are set too, because the app reads those. Native git launches the native tool, and the conflicts dialog hands the file to git mergetool so git stages the result itself.

The Console tab is your login shell, in the repository, with your prompt and dotfiles and SSH agent. Progress dialogs (rebase, merge, pull, cherry-pick) run their command on a real pseudo-terminal, so an interactive rebase with a terminal editor works and the output is coloured. Stage-by-patch asks its questions in the process dialog and you answer in its input line. User scripts and external tools are Linux programs unless they’re obviously Windows ones; write them as you would on Linux. “Tools > Linux terminal” opens your terminal emulator in the repository.

What doesn’t work is short. PowerShell user scripts silently do nothing, because Wine’s powershell.exe is a stub that exits 0. The Gource and AutoCompileSubmodules plugins want programs the prefix hasn’t got. And don’t run without the bridge unless you’ve read docs/running-under-wine.md: GITEXT_GIT_BRIDGE=0 in the environment turns it off, and then the prefix needs a Windows git of its own.

Updating and removing

“Help > Check for updates” asks the fork for its latest release, and if there’s a newer one it offers to install it. The app closes, the update runs once every window has gone, and the app comes back. It won’t kill a window to get on with the job; if something stays open it gives up, having changed nothing.

Re-running the curl command does the same from outside the app. Pipe it to sh -s -- --help instead of sh for the options; sh -s -- uninstall removes everything but the prefix, and uninstall --purge removes that too.

Versions read 7.3.0.6-dev-wine: upstream’s version, then a build number, and -dev while upstream hasn’t released that base yet.

When it breaks

GITEXT_GIT_BRIDGE_LOG=<file> in the environment before gitext-wine lists every command the bridge ran. After a Wine upgrade, run through this:

  • open the Console tab and switch windows away and back
  • “Edit commit” on a throwaway branch
  • “Open with…” on a file
  • resolve a conflict with the merge tool
  • fetch from a remote
  • click a tile on the dashboard’s recent repositories

docs/running-under-wine.md in the branch, and in the Linux tarball, has everything else, including what turned up in every place the app shells out and the Wine bugs that were worked around in code. It also covers running with a Windows git in the prefix, if you must.

Everything above was worked out on Arch, against Wine 11 and .NET 10 in a KDE Wayland session.