Published in Articles on by Michiel van Oosterhout ~ 8 min read

Git is one of the most, if not the most, popular version control software in the world. An installer for Windows is available, but as we will soon see this installer presents us with no less than 14 pages (as of version 2.39.0.2) of options! Since laziness is one of the great virtues of a programmer, we will automate the installation using a single script.

The Git for Windows installer

The Git for Windows installer can be downloaded from git-scm.org or from github.com/git-for-windows. Git for Windows uses an Inno Setup installer which is compiled from this setup script file. This type of file is documented here. By analyzing the setup script we can discover how the installer works, and how we can drive it from a command line.

Using winget instead

Git for Windows can also be installed using Windows Package Manager (also known by the name of its official command-line client, winget). The Git for Windows package is based on the same Inno Setup installer (see the package manifest), but using winget is more suitable for unattended automated installation.

Downloading the Git for Windows installer using `winget`
Downloading the Git for Windows installer using winget

When run interactively (winget install Git.Git --source winget --interactive --accept-source-agreements, see install command) the installer presents 14 pages with settings that require manual input or selection. Some of these settings are standard for Inno Setup installers, and as such can be set via the command line using documented parameters.

Using winget's built-in support for Inno Setup

Because winget has built-in support for Inno Setup installers, some of winget's parameters map to parameters of the installer. For example, the first setting (shown in the second page after the license page) is the location where Git for Windows should be installed. We can change the setting via the command line using winget's --location parameter which maps to the installer's /DIR parameter.

Git for Windows installer's destination location setting
Git for Windows installer's destination location setting

Parameters for the installer can also be provided via winget's --override parameter. Inno Setup's parameters are documented here. So --silent for example can be replaced with --override /VERYSILENT.

With --override we can change the settings in the first 3 pages following the license page:

  1. Select Destination Location
    /DIR="C:\Program Files\Git"
  2. Select Components
    /COMPONENTS=assoc
    We can find the components at the time of writing in the setup script here. Here we selected only one component. Use , to select multiple components.
  3. Select Start Menu Folder
    /GROUP=Git

The rest of the settings can be changed via --override using undocumented parameters, described in detail in the next section.

Understanding Git for Windows' custom installer pages

At the time of writing there are 11 additional pages in the Git for Windows installer. These pages are custom-built using Inno Setup's Pascal scripting (see [Code] section in the setup script). Every custom page presets its settings based on one of 3 sources:

  • the input given during a previous install
    (saved in mingw64\etc\install-options.txt);
  • a file created by running the installer with the /SAVEINF= parameter;
  • custom /o:key=value parameters in the command line.

For example, the parameter /o:DefaultBranchOption=main changes the setting on the 5th page ("Adjusting the name of the initial branch in new repositories") to "Override the default branch name for new repositories." Here DefaultBranchOption is the key and main is the value. To find the supported keys and values for each custom page, we need to search the setup script for calls to ReplayChoice (example).

A custom page of the Git for Windows installer
A custom page of the Git for Windows installer

These are the custom pages and the corresponding parameters with some sensible defaults:

  1. Choosing the default editor used by Git
    /o:EditorOption=Nano

Corresponds to git config --system core.editor nano.exe 1. When using /o:EditorOption=VIM, core.editor will be removed, causing Git to use the EDITOR environment variable.

  1. Adjusting the name of the initial branch in new repositories
    /o:DefaultBranchOption=main

This corresponds to git config --system init.defaultBranch main.

  1. Adjusting your PATH environment
    /o:PathOption=Cmd

Adds cmd to the PATH environment variable. When using /o:PathOption=CmdTools, mingw64\bin and usr\bin are also added.

  1. Choosing the SSH executable
    /o:SSHOption=ExternalOpenSSH

This removes the bundled SSH binaries from the installation, so C:\Windows\System32\OpenSSH\ssh.exe is automatically used instead. (This is present if the optional Windows feature OpenSSH Client is enabled). When using /SSHOption=Plink then it corresponds to git config --system ssh.variant putty (or tortoiseplink).

  1. Choosing HTTPS transport backend
    /o:CURLOption=WinSSL

Corresponds to git config --system http.sslBackend schannel.

  1. Configuring the line ending conversions
    /o:CRLFOption=CRLFAlways

Corresponds to git config --system core.autocrlf true. LFOnly maps to input and CRLFCommitAsIs maps to false.

  1. Configuring the terminal emulator to use with Git Bash
    /o:BashTerminalOption=ConHost

Patches the git-bash.exe executable (actually Git Wrapper) to use this command line to start Bash: SHOW_CONSOLE=1 APPEND_QUOTE=1 @@COMSPEC@@ /S /C ""@@EXEPATH@@\usr\bin\bash.exe" --login -i". Since this executes what is in the ComSpec environment variable, and since that is typically C:\Windows\system32\cmd.exe, Bash will end up being hosted by either Console Window Host or Windows Terminal (See The Windows command-line interface, part 2).

  1. Choose the default behavior of `git pull`
    /o:GitPullBehaviorOption=Merge

Corresponds to git config --system pull.rebase=false. Rebase maps to true, and FFOnly corresponds to git config --system pull.ff only.

  1. Choose a credential helper
    /o:UseCredentialManager=Enabled

Corresponds to git config --system credential.helper manager and git config --system credential.https://dev.azure.com.useHttpPath true. This will use Git Credential Manager, which replaces both the .NET Framework-based Git Credential Manager for Windows and the Java-based Git Credential Manager for Mac and Linux and is installed in mingw64\bin.

  1. Configuring extra options

(Using Auto instead of Enabled effectively does not enable these.)

  • Enable file system caching
    /o:PerformanceTweaksFSCache=Enabled (corresponds to git config --system core.fscache=true)
  • Enable symbolic links
    /o:EnableSymlinks=Auto (corresponds to git config --system core.symlinks=true)
  1. Configuring experimental options

(Using Auto instead of Enabled effectively does not enable these.)

  • Enable experimental support for pseudo consoles
    /o:EnablePseudoConsoleSupport=Auto (corresponds to MSYS=enable_pcon in mingw64\etc\git-bash.config)
  • Enable experimental built-in file system monitor
    /o:EnableFSMonitor=Auto (corresponds to git config --system core.fsmonitor true)

At the time of writing the following experimental features were present in the setup script, but not made available in the installer yet.

  • Enable experimental, builtin difftool
    /o:EnableBuiltinDifftool=Auto (corresponds to git config --system difftool.useBuiltin true)
  • Enable experimental, built-in rebase
    /o:EnableBuiltinRebase=Auto (corresponds to git config --system rebase.useBuiltin true)
  • Enable experimental, built-in stash
    /o:EnableBuiltinStash=Auto (corresponds to git config --system stash.useBuiltin true)
  • Enable experimental, built-in add -i/-p
    /o:EnableBuiltinInteractiveAdd=Auto (corresponds to git config --system add.interactive.useBuiltin true)
Git Bash hosted by Console Window Host and showing some of Git's system-wide settings as set by the installer
Git Bash hosted by Console Window Host and showing some of Git's system-wide settings as set by the installer

The installation script

The Windows PowerShell script below uses winget and the --override parameter to install Git for Windows:

# Define parameters for the installer
$innoParameters = @{
    ALLUSERS = $true
    VERYSILENT = $true
    SUPPRESSMSGBOXES = $true
    NORESTART = $true
    FORCECLOSEAPPLICATIONS = $true
}
$innoComponents = @(
    "assoc"
)

# Define parameters for custom installer pages
$customParameters = @{
    EditorOption = "VIM"
    DefaultBranchOption = "main"
    PathOption = "Cmd"
    SSHOption = "ExternalOpenSSH"
    CURLOption = "WinSSL"
    CRLFOption = "CRLFAlways"
    BashTerminalOption = "ConHost"
    GitPullBehaviorOption = "Merge"
    UseCredentialManager = "Enabled"
    PerformanceTweaksFSCache = "Enabled"
}

# Map parameters to tokens for the command line
$parameters = $innoParameters.GetEnumerator() | ForEach-Object {
    if ($_.Value -is [bool])
    {
        if ($_.Value)
        {
            "/$($_.Key)"
        }
    }
    else
    {
        "/$($_.Key)=\`"$($_.Value)\`""
    }
}
$parameters += "/COMPONENTS=$([string]::Join(",", $innoComponents))"
$parameters += $customParameters.GetEnumerator() | ForEach-Object { "/o:$($_.Key)=$($_.Value)" }

$override = [string]::Join(" ", $parameters)

# Install Git for Windows
& winget install Git.Git -s winget --accept-source-agreements --override "$override"

# Remove some registry keys
@("Git Bash", "Git CMD") | ForEach-Object {
    $path = Join-Path "HKCU:\Console" $_
    if (Test-Path -Path $path)
    {
        # Remove keys
        Remove-Item $path -Force -Recurse
    }
}

Even though we did not select the consolefont component, the installer still creates two keys in the Windows Registry to configure the font for Console Window Host windows. Since we already took full control of this kind of configuration in Configuring Console Window Host, the script removes these keys.

Git installs a program called Git Cmd, which starts Windows Command Processor with a custom environment. One of the additional environment variables is listed on Git's website, so it is probably a good idea to set it:

cmd /c setx HOME %HOMEDRIVE%%HOMEPATH%

Summary

The download and installation of Git for Windows can be fully automated using winget, but we had to read the setup script to discover the parameters that control the settings used by the installer's custom pages. After installation, most of these settings can still be changed using git config.

Updates

  • Added environment variables used by Git Cmd.

  1. With Git for Windows, git config --system corresponds to the etc\gitconfig file. ↩︎