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.

  1. Open your profile for editing:

    notepad $PROFILE
    
  2. 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
    }
}
  1. 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.