Managing Windows Dotfiles with a Git Bare Repo
Managing dotfiles on Windows can be a challenge if you want to keep your home directory clean without relying on symlinks or complex management tools. A “Git Bare Repository” approach allows you to track configuration files (like .gitconfig, .vimrc, or PowerShell profiles) directly in their original locations.
The Bare Repository Concept
A bare repository is a Git repository without a working directory. By pointing the “working tree” to your home directory while keeping the “git directory” separate (e.g., in ~/.cfg), you can manage your files across the system as if they were in a single repo, without Git interfering with other files in your home folder.
Initial Setup
Run these commands in PowerShell to initialize your dotfiles repository:
# Create the bare repo
git init --bare $HOME/.cfg
# Use git commands to configure it to ignore untracked files by default
# This prevents 'git status' from showing every single file in your USERPROFILE
git --git-dir=$HOME/.cfg/ --work-tree=$HOME config --local status.showUntrackedFiles no
PowerShell Profile Configuration
To make this convenient to use, we define a function cfg (or any name you prefer) in your PowerShell profile. This function wraps the git command with the appropriate directory flags.
-
Open your profile for editing:
notepad $PROFILE -
Add the following function and autocomplete registration:
# Function to manage dotfiles via the bare repo
function cfg {
& git --git-dir=$HOME/.cfg/ --work-tree=$HOME $args
}
# Enable git-like autocomplete for the 'cfg' command
if (Get-Command "git" -ErrorAction SilentlyContinue) {
Register-ArgumentCompleter -CommandName 'cfg' -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
# This takes the current line, replaces 'cfg' with 'git', and asks git for completions
$currentCommand = $commandAst.ToString()
$gitCommand = "git " + $currentCommand.Substring(4)
# Note: This is a simplified version. For full posh-git support,
# you might need more complex logic, but this gets basic subcommands working.
[System.Management.Automation.CommandCompletion]::CompleteInput(
$gitCommand,
$cursorPosition + 1,
$null
).CompletionMatches
}
}
- Reload your profile:
. $PROFILE
Daily Usage
Now you can use cfg exactly like you use git, but it only tracks the files you explicitly add.
Adding and Committing
# Track your git configuration
cfg add .gitconfig
# Track your PowerShell profile
cfg add $PROFILE
# Commit and see status
cfg status
cfg commit -m "initial dotfiles backup"
Remote Backup
cfg remote add origin https://github.com/yourusername/dotfiles.git
cfg push -u origin main
Setting Up on a New Machine
When setting up a new Windows machine, you can “clone” your dotfiles like this:
# Alias must be defined first
function cfg { & git --git-dir=$HOME/.cfg/ --work-tree=$HOME $args }
# Clone the repo as bare
```powershell
git clone --bare https://github.com/$env:USERNAME/dotfiles.git $HOME/.cfg
Checkout the files into your home directory
cfg checkout
If there are conflicts (files already exist), move them or backup:
cfg checkout 2>&1 | ForEach-Object { if ($_ -match “would be overwritten”) { … } }
Set the flag to hide untracked files again
cfg config –local status.showUntrackedFiles no
This method is lightweight, portable, and requires no third-party dependencies other than Git itself.