How to Install Git and Set Up a Git Repository on Windows Server 2025

Git has become the universal standard for source control, and knowing how to install, configure, and host it correctly on Windows Server 2025 is an essential skill for any server administrator or DevOps engineer. Unlike a developer workstation setup, a server-side Git installation often serves multiple teams, acts as a bare repository host, enforces commit hooks for policy, and must integrate cleanly with SSH key-based authentication and credential management tools. This guide covers every step — from downloading the Git for Windows installer, through silent automated installation, global configuration, SSH key management, hosting a bare repository, configuring Git hooks, and integrating the posh-git PowerShell module for a productivity boost in the PowerShell prompt.

Prerequisites

  • Windows Server 2025 with internet access (or access to a local mirror)
  • PowerShell 7.4 or later (run $PSVersionTable.PSVersion to check)
  • A standard or administrator user account (administrator required for system-wide install)
  • An account on GitHub, GitLab, or an internal Git server if you plan to push to a remote
  • Windows Firewall rules allowing outbound HTTPS (port 443) and SSH (port 22) if connecting to remote hosts

Step 1: Downloading Git for Windows

The official Git for Windows installer is maintained at git-scm.com. For server environments, always download a specific version rather than relying on a “latest” redirect so that your installations are reproducible. You can use PowerShell to download the installer directly without opening a browser.

# Download Git for Windows installer (replace version as needed)
$gitVersion   = '2.47.1'
$installerUrl = "https://github.com/git-for-windows/git/releases/download/v${gitVersion}.windows.1/Git-${gitVersion}-64-bit.exe"
$outFile      = "$env:TEMPGit-${gitVersion}-64-bit.exe"

Write-Host "Downloading Git $gitVersion..."
Invoke-WebRequest -Uri $installerUrl -OutFile $outFile -UseBasicParsing

# Verify the download exists
if (-not (Test-Path $outFile)) {
    throw "Download failed. File not found at $outFile"
}
Write-Host "Download complete: $outFile"

Step 2: Silent Installation

On a server, a silent (unattended) install is preferred over an interactive GUI wizard. Git for Windows uses an Inno Setup-based installer that accepts /SILENT or /VERYSILENT switches along with /NORESTART. You can also supply an /INF file to pre-configure component choices, but the defaults are suitable for most server installs.

$gitVersion   = '2.47.1'
$installerPath = "$env:TEMPGit-${gitVersion}-64-bit.exe"

# Key installer options:
# /VERYSILENT  — no progress dialog
# /NORESTART   — never reboot automatically
# /NOCANCEL    — no cancel button (useful for unattended)
# /COMPONENTS  — comma-separated list of components to install
# /o:PathOption=UseBash — keep bash as default (server-friendly)

$installArgs = @(
    '/VERYSILENT',
    '/NORESTART',
    '/NOCANCEL',
    '/SUPPRESSMSGBOXES',
    '/LOG="C:WindowsTempgit_install.log"',
    '/o:PathOption=Cmd',           # Add Git to PATH (Cmd and PowerShell)
    '/o:CRLFOption=CRLFAlways',    # Commit LF, checkout CRLF (Windows default)
    '/o:BashTerminalOption=ConHost',
    '/o:EnableSymlinks=Enabled'
)

Write-Host "Installing Git silently..."
$proc = Start-Process -FilePath $installerPath -ArgumentList $installArgs -Wait -PassThru -NoNewWindow

if ($proc.ExitCode -ne 0) {
    throw "Git installer exited with code $($proc.ExitCode). Check C:WindowsTempgit_install.log"
}

Write-Host "Git installed successfully."

# Reload PATH in the current session without logging out
$env:Path = [System.Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' +
            [System.Environment]::GetEnvironmentVariable('Path', 'User')

git --version

Step 3: Configuring Git Globally

After installation, set the global Git configuration for the account that will be performing commits. On a server used by multiple people, each user should run these commands under their own account. The core.autocrlf setting is particularly important on Windows — setting it to true ensures that files are stored in the repository with Unix line endings (LF) and checked out with Windows line endings (CRLF).

# Identity — used in commit metadata
git config --global user.name  "Build Agent"
git config --global user.email "[email protected]"

# Line ending normalisation (critical for cross-platform teams)
git config --global core.autocrlf true

# Default branch name for new repositories
git config --global init.defaultBranch main

# Use Windows credential manager as the credential helper
git config --global credential.helper manager

# Improve diff output
git config --global core.pager "less -F -X"

# Safe directory (important on Windows Server when running Git as a service account)
git config --global --add safe.directory '*'

# Verify
git config --global --list

If your server uses a proxy, add proxy settings with git config --global http.proxy http://proxy.example.com:8080.

Step 4: Generating an SSH Key and Adding It to GitHub or GitLab

SSH key authentication eliminates the need to enter passwords when pushing to remote repositories, and it is far more secure than password-based HTTPS authentication for automated scripts. Generate an Ed25519 key (preferred over RSA for new keys) and then add the public key to your remote provider.

# Generate an Ed25519 SSH key pair
# -t ed25519      : key type
# -C              : comment (usually your email)
# -f              : output file path
# -N ""           : empty passphrase (suitable for service accounts; use a passphrase for human accounts)

$keyPath = "$env:USERPROFILE.sshid_ed25519"

if (-not (Test-Path "$env:USERPROFILE.ssh")) {
    New-Item -ItemType Directory -Path "$env:USERPROFILE.ssh" | Out-Null
}

ssh-keygen -t ed25519 -C "[email protected]" -f $keyPath -N '""'

# Display the public key — this is what you add to GitHub/GitLab
Write-Host "`nPublic key (add this to your Git provider):"
Get-Content "$keyPath.pub"

# Start the SSH agent and add the key (useful for interactive sessions)
$sshAgent = Get-Service -Name 'ssh-agent' -ErrorAction SilentlyContinue
if ($sshAgent -and $sshAgent.Status -ne 'Running') {
    Set-Service -Name 'ssh-agent' -StartupType Automatic
    Start-Service -Name 'ssh-agent'
}
ssh-add $keyPath

# Test the connection to GitHub
ssh -T [email protected]

Copy the output of Get-Content "$keyPath.pub" and paste it into GitHub under Settings → SSH and GPG keys → New SSH key, or in GitLab under User Settings → SSH Keys.

Step 5: Initializing a Bare Repository for Team Use

A bare repository contains only the Git object database with no working tree. It is the correct format for a centralized repository that team members push to and pull from — equivalent to what GitHub hosts internally. Create one on your Windows Server 2025 machine to act as an internal Git server.

# Create a directory for your repositories
$repoRoot = 'D:GitRepositories'
$repoName = 'MyProject.git'

if (-not (Test-Path $repoRoot)) {
    New-Item -ItemType Directory -Path $repoRoot | Out-Null
}

# Initialize the bare repository
git init --bare "$repoRoot$repoName"

# Set ownership permissions so team members can push
# Replace DOMAINGitUsers with your actual group
$acl  = Get-Acl -Path "$repoRoot$repoName"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    'DOMAINGitUsers',
    'Modify',
    'ContainerInherit,ObjectInherit',
    'None',
    'Allow'
)
$acl.SetAccessRule($rule)
Set-Acl -Path "$repoRoot$repoName" -AclObject $acl

Write-Host "Bare repository created at $repoRoot$repoName"
Write-Host "Clone URL (network): \$(hostname)GitRepositories$repoName"

Team members can now clone this repository using either UNC paths (git clone \serverGitRepositoriesMyProject.git) or SSH if you configure an SSH server on the Windows Server.

Step 6: Setting Up Git Hooks

Git hooks are scripts that run automatically at specific points in the Git workflow. On a bare server repository, server-side hooks such as pre-receive and post-receive are most useful for enforcing policies and triggering CI/CD builds. On Windows, hooks are shell scripts (bash) or can be PowerShell wrappers.

# Create a post-receive hook that sends a notification
$hookPath = "D:GitRepositoriesMyProject.githookspost-receive"

$hookContent = @'
#!/bin/sh
# post-receive hook — trigger CI build on push

while read oldrev newrev refname; do
    branch=$(git rev-parse --abbrev-ref "$refname")
    echo "Push received on branch: $branch"

    if [ "$branch" = "main" ]; then
        echo "Triggering CI pipeline for main branch..."
        powershell.exe -NonInteractive -File "D:GitHookstrigger-ci.ps1" -Branch "$branch" -Commit "$newrev"
    fi
done
'@

$hookContent | Out-File -FilePath $hookPath -Encoding ascii -NoNewline

# On Windows, hooks need to be executable — set the file attribute
# (Git on Windows checks for execute bit via the Cygwin layer in bash hooks)
# Alternatively, name the hook with a .cmd extension for Windows batch runner
Write-Host "Hook written to $hookPath"

Step 7: Git Credential Manager

Git Credential Manager (GCM) ships with Git for Windows and securely stores credentials in the Windows Credential Manager, eliminating repeated password prompts for HTTPS remotes. GCM is configured automatically during installation when you choose the Git Credential Manager component.

# Verify GCM is active
git credential-manager --version

# List stored credentials
cmdkey /list | Select-String -Pattern 'git'

# Force GCM to re-authenticate for a specific host
git credential-manager erase
# Then run: git ls-remote https://github.com/yourrepo/yourproject.git
# GCM will prompt and cache the new credential

# For non-interactive (service account) scenarios, use a PAT stored in env vars
$env:GCM_CREDENTIAL_STORE = 'plaintext'   # or 'secretservice' on Windows with LSA
$env:GITHUB_TOKEN = (Get-Content 'C:Secretsgithub_token.txt' -Raw).Trim()

Step 8: Using Git in PowerShell with posh-git

The posh-git PowerShell module adds Git status information directly to your PowerShell prompt and provides tab completion for Git commands and branch names, making Git operations much faster when working interactively on the server.

# Install posh-git from the PowerShell Gallery
Install-Module -Name posh-git -Scope CurrentUser -Force -AllowClobber

# Import in the current session
Import-Module posh-git

# To load automatically, add to your PowerShell profile
$profilePath = $PROFILE.CurrentUserAllHosts
if (-not (Test-Path $profilePath)) {
    New-Item -ItemType File -Path $profilePath -Force | Out-Null
}

$profileLine = 'Import-Module posh-git'
$profileContent = Get-Content $profilePath -ErrorAction SilentlyContinue
if ($profileContent -notcontains $profileLine) {
    Add-Content -Path $profilePath -Value "`n$profileLine"
    Write-Host "posh-git added to PowerShell profile at $profilePath"
}

# Verify — navigate to a git repository and check the prompt
Set-Location 'D:GitRepositoriesMyProject'
Write-Host "Git status: $(git status --short)"

Installing and configuring Git on Windows Server 2025 is straightforward when approached systematically. A silent installation ensures consistency across all your servers, global configuration settings align the tool with your team’s standards, SSH key authentication provides secure passwordless access to remote hosts, and a centralized bare repository gives your team a self-hosted collaboration point without requiring a full-featured platform like Gitea or GitHub Enterprise. Add posh-git to the mix and your PowerShell sessions become first-class Git environments, completing a professional-grade Git setup worthy of a production Windows Server environment.