Why Git on Windows Server 2022

Windows Server 2022 is frequently used as a build server, CI/CD agent, or a centralized repository host for teams that cannot or do not want to use hosted services like GitHub or GitLab. Installing Git directly on the server gives you bare repositories for team sharing, hooks that trigger builds, and a local mirror of remote repositories for air-gapped environments. This tutorial covers installation, essential configuration, and the full day-to-day Git workflow on Windows Server 2022.

Installing Git for Windows

The two most common installation methods on Windows Server 2022 are winget and the standalone Git installer. If App Installer is available, the fastest method is:

winget install --id Git.Git -e --source winget

This installs the latest stable Git for Windows release, adds git.exe to the system PATH, and includes Git Bash, Git GUI, and Git Credential Manager. Accept the default options unless you have specific needs around the default text editor or line ending behavior.

If winget is not available (common on Server Core or older base images), download the installer directly and run it silently:

$gitInstaller = "$env:TEMPGit-Installer.exe"
Invoke-WebRequest -Uri "https://github.com/git-for-windows/git/releases/download/v2.45.2.windows.1/Git-2.45.2-64-bit.exe" `
                  -OutFile $gitInstaller
Start-Process -FilePath $gitInstaller `
              -ArgumentList "/VERYSILENT /NORESTART /COMPONENTS=icons,extregshellhere,assoc,assoc_sh" `
              -Wait
Remove-Item $gitInstaller

After installation, verify Git is accessible in the current shell:

git --version
# git version 2.45.2.windows.1

Essential Git Configuration

Before using Git, configure your identity and environment settings. These settings are written to C:Usersusername.gitconfig (global) or C:ProgramDataGitconfig (system-wide).

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

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

# Credential helper — Git Credential Manager ships with Git for Windows
git config --global credential.helper manager

# Line ending behavior: checkout Windows CRLF, commit Unix LF
git config --global core.autocrlf true

# For servers that only store and serve repos (no editing), use input mode
# git config --global core.autocrlf input

# Default editor (use notepad, code, or vim)
git config --global core.editor "code --wait"

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

# Prune stale remote-tracking branches on fetch
git config --global fetch.prune true

# Show branch tracking info on git status
git config --global status.showUntrackedFiles all

View all active configuration and where each setting is defined:

git config --list --show-origin

Initializing a Repository

To start tracking a project already on disk, navigate to the project folder and initialize a repository:

cd C:ProjectsMyApp
git init
git add .
git commit -m "Initial commit"

The git add . command stages all files. Use a .gitignore file to exclude build outputs, secrets, and binary artifacts before staging. A minimal .gitignore for a .NET project:

bin/
obj/
*.user
.vs/
*.suo
packages/
*.nupkg
appsettings.Production.json

Create this file in the project root before the first git add to avoid committing unwanted files.

Cloning a Remote Repository

Cloning copies an existing repository — including all history and branches — to your local machine or server:

# Clone over HTTPS
git clone https://github.com/yourorg/yourrepo.git C:Projectsyourrepo

# Clone over SSH (after setting up SSH keys)
git clone [email protected]:yourorg/yourrepo.git C:Projectsyourrepo

# Clone a specific branch only
git clone --branch release/2.0 --single-branch https://github.com/yourorg/yourrepo.git

# Shallow clone: only most recent 50 commits (faster for CI agents)
git clone --depth 50 https://github.com/yourorg/yourrepo.git

The Basic Daily Workflow

The typical Git workflow on a feature branch follows this sequence:

# Check current status
git status

# Pull latest changes from the remote tracking branch
git pull origin main

# Create and switch to a new feature branch
git checkout -b feature/add-login-page

# Stage specific files
git add src/Login.cs src/LoginView.cshtml

# Stage all tracked modified files
git add -u

# Commit with a descriptive message
git commit -m "Add login page with form validation"

# Push the branch to the remote
git push origin feature/add-login-page

# After the pull request is merged, clean up
git checkout main
git pull origin main
git branch -d feature/add-login-page

To see what changed between your working directory and the last commit:

# Unstaged changes
git diff

# Staged changes (what will be in the next commit)
git diff --cached

# Commit history — one line per commit
git log --oneline --graph --decorate --all

Configuring Git Credential Manager

Git Credential Manager (GCM) is installed automatically with Git for Windows and handles authentication for HTTPS remotes. It stores credentials in the Windows Credential Store (managed via Credential Manager in Control Panel). For non-interactive server scenarios, configure GCM to use a specific store:

# Use Windows Credential Manager (default, interactive)
git config --global credential.credentialStore wincredman

# For headless CI agents, store in plaintext file (less secure — limit with NTFS permissions)
git config --global credential.credentialStore plaintext

# Confirm the current helper
git config --global credential.helper

To pre-populate credentials without an interactive prompt (useful for service accounts):

git credential approve << EOF
protocol=https
host=github.com
username=svc-build
password=ghp_YourPersonalAccessToken
EOF

Setting Up SSH Keys for GitHub and GitLab

SSH key authentication avoids storing passwords and is preferred for server-to-server communication. Generate a key pair on the server:

# Generate Ed25519 key (preferred over RSA)
ssh-keygen -t ed25519 -C "[email protected]" -f "$env:USERPROFILE.sshid_ed25519"

# For legacy systems that require RSA
ssh-keygen -t rsa -b 4096 -C "[email protected]" -f "$env:USERPROFILE.sshid_rsa"

Display the public key to copy it to GitHub or GitLab:

Get-Content "$env:USERPROFILE.sshid_ed25519.pub"

On GitHub: go to Settings > SSH and GPG keys > New SSH key, paste the public key, and save. Test the connection:

ssh -T [email protected]
# Hi username! You've successfully authenticated.

If using a non-standard key file, create or edit ~/.ssh/config to map the host:

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Bare Repositories as Server-Side Repos

A bare repository stores only Git’s internal data without a working directory. This is the correct format for a centralized server repository that multiple developers push to and pull from:

# Create a bare repo (conventionally named with .git suffix)
git init --bare C:ReposMyApp.git

# Developers clone from the server path or a UNC share
git clone \SERVERReposMyApp.git C:ProjectsMyApp

# Or over SSH if the server is running OpenSSH
git clone ssh://administrator@SERVER/C:/Repos/MyApp.git

Set appropriate NTFS permissions on the bare repo directory so that only authorized users or service accounts can read and write it.

Git Hooks on Windows

Git hooks are scripts in the .git/hooks directory that run automatically at specific points in the Git workflow. On Windows, hooks are plain text files with no extension that Git executes. The most useful server-side hook for a bare repo is post-receive, which triggers after a push is accepted:

# File: C:ReposMyApp.githookspost-receive
# No file extension; must be executable (chmod not needed on Windows, Git runs it directly)

#!/bin/sh
echo "Triggering CI build..."
powershell.exe -NonInteractive -File "C:\Scripts\trigger-build.ps1"

A client-side pre-commit hook can enforce code standards before a commit is recorded:

# File: .git/hooks/pre-commit
#!/bin/sh
# Run .NET format check; exit 1 aborts the commit
dotnet format --verify-no-changes --no-restore
if [ $? -ne 0 ]; then
    echo "Code formatting violations found. Run 'dotnet format' and re-commit."
    exit 1
fi

Useful Git Aliases

Aliases reduce repetitive typing and encode your preferred workflow options. Add these to your global config:

git config --global alias.st "status -sb"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.co "checkout"
git config --global alias.br "branch -vv"
git config --global alias.undo "reset HEAD~1 --mixed"
git config --global alias.save "stash push -m"
git config --global alias.pop "stash pop"
git config --global alias.aliases "config --get-regexp alias"

After adding these, git lg shows a compact, visual branch graph, and git undo safely un-commits the last commit while preserving the changes as unstaged edits. These small quality-of-life improvements significantly speed up daily Git work on Windows Server 2022.