Step-by-Step Guide to Using Git for Dotfile Management on macOS and Linux

Managing your dotfiles with Git on Linux and macOS allows you to securely back up important configuration files, including shell aliases and editor settings. This guide provides a clear, step-by-step approach to organising, tracking, and synchronising your dotfiles in a central repository. As a result, you can quickly set up a consistent environment on any new machine or server with ease.

Prerequisites #

Before you begin, ensure you have:

  • GitHub account
    For hosting and syncing dotfiles.
  • Linux server (e.g. Linode)
    SSH access for remote setup and testing.
  • Basic command-line skills
    Navigating, editing files, and running commands.
  • Custom shell aliases set up
    These will be tracked in the dotfiles repository.

Want to learn more about shell aliases and functions? Read my guide to get started.

Overview #

Directory Location

All dotfiles are stored and managed in the directory: ~/dotfiles.

Tracked Files

  • Shell configuration:
    • .aliases
    • .aliases-linux
    • .aliases-macos
    • .functions
    • .functions-linux
    • .functions-macos
  • Editor configuration:
    • .vimrc

Step 1: Install Required Tools #

On Linux (Ubuntu):

bash
sudo apt install git gh -y

On macOS:

bash
brew install git gh

Verify installation:

bash
git --version
gh --version

Authenticate GitHub CLI:

bash
gh auth login

When prompted, select:

  • GitHub.com
  • Protocol: SSH
  • SSH public key: skip
  • Authenticate: browser

Follow the browser instructions to complete authentication.

Step 2: Set Up SSH Access #

Create SSH Key #

Generate a new SSH key using the ed25519 algorithm:

bash
ssh-keygen -t ed25519 -C "<[email protected]>" -f ~/.ssh/<key_name> -N ""

Notes:

  • Replace <key_name> with a descriptive name, e.g. github
  • -N "" sets an empty passphrase

Add SSH Key to Agent #

For Linux

Start the SSH agent (if not already running):

bash
eval "$(ssh-agent -s)"

Add private key to the agent:

bash
ssh-add ~/.ssh/<key_name>

For macOS

Add key to the agent and store the passphrase securely in the macOS keychain:

bash
ssh-add --apple-use-keychain ~/.ssh/<key_name>

This command:

  • Adds the SSH key to the running SSH agent
  • Saves your passphrase in the macOS keychain for seamless use in future sessions

Edit SSH Config #

Open SSH config file:

bash
vim ~/.ssh/config

For Linux

GitHub supports SSH connections only on:

  • Port 22 (default)

  • Port 443 via ssh.github.com (useful when port 22 is blocked)

When using the default SSH port (22), add:

~/.ssh/config
Host github.com
  User git
  IdentityFile ~/.ssh/<key_name>
  IdentitiesOnly yes

When using a custom SSH port, add:

~/.ssh/config
Host github.com
  HostName ssh.github.com
  Port 443
  User git
  IdentityFile ~/.ssh/<key_name>
  IdentitiesOnly yes

Explanation:

  • Host github.com: Alias used in Git operations (e.g. [email protected]).
  • HostName: Actual hostname to connect to (only needed when using a non-default port).
  • Port: Use 443 only if port 22 is blocked.
  • User git: Required for GitHub SSH authentication.
  • IdentityFile: Path to your private key (e.g. ~/.ssh/github).
  • IdentitiesOnly yes: Ensures SSH uses only the specified identity file.

Set and verify permissions:

bash
chmod 600 ~/.ssh/config
ls -l ~/.ssh/config

For macOS

Use default port 22, and enable keychain and agent integration.

Add:

~/.ssh/config
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/<key_name>
  IdentitiesOnly yes
  UseKeychain yes
  AddKeysToAgent yes

Explanation:

  • UseKeychain yes: (macOS) Stores key passphrase in the macOS Keychain.
  • AddKeysToAgent yes: (macOS) Automatically adds the key to the SSH agent.

Add SSH Key to GitHub #

Display public key:

bash
cat ~/.ssh/<key_name>.pub

Use this output to add the key to your GitHub account.

Add SSH Key to GitHub:

Pro tip: Use a consistent naming convention for SSH keys: <host>-<role>-<usage>

  1. Go to GitHub Settings → SSH and GPG keys
  2. Click New SSH key
  3. Fill in:
    • Title: e.g. linode-blog-github
    • Key type: Authentication key
    • Key: Paste your copied public key
  4. Click Add SSH key

Test SSH GitHub Connection #

Run:

bash
ssh -T [email protected]

If prompted the first time, type yes to accept GitHub’s SSH fingerprint.

Expected output:

text
Hi <user>! You've successfully authenticated, but GitHub does not provide shell access.

Step 3: Set Up Local Repository #

Configure Git Identity #

Set global Git username and email:

bash
git config --global user.name "<name>"
git config --global user.email "<[email protected]>"

This information will be associated with your commits.

Verify Git configuration:

bash
git config --list

Press q to exit.

Initialise the Repository #

Create the dotfiles directory and initialise it as a Git repository:

bash
mkdir -p ~/dotfiles
cd ~/dotfiles
git init

This creates a .git folder, enabling Git to track changes in the directory. You’re now ready to start managing your dotfiles with version control.

Create .gitignore #

Goal: exclude unnecessary, sensitive, or system-specific files.

Create the file:

bash
vim ~/dotfiles/.gitignore

Add:

~/dotfiles/.gitignore
# Backup Files
*.bak

# Logs and Temporary Files
*.log
*.tmp

# Editor and Project Configuration
.prettierignore
.prettierrc
.vscode/
.workspace

# Git-related Files
.git/
.gitignore~
.gitmessage

# OS and System Files
.DS_Store
.Spotlight-V100
.Trashes

# Shell Configuration and History
.bashrc
.bash_history
.zshrc
.zsh_history

# Secrets and Credentials
.env
*.key
*.pem

Create .gitmessage #

This template ensures clear, consistent commit messages by following standard conventions.

Create template file:

bash
vim ~/dotfiles/.gitmessage

Add:

~/dotfiles/.gitmessage
# Commit Message Guidelines

# Commit message should complete the sentence:  
# “If applied, this commit will...”

# Summary line:
# - Max 50 characters, no punctuation  
# - Format: <type>(<scope>): <keyword> <summary>  
# Examples:
# feat(alias): add gs alias for git status
# fix(func): correct extract() tar.gz handling
# refactor(core): move aliases to separate file  

type(scope): keyword summary

# Commit Types:
# - chore:     Maintenance or deletions
# - docs:      Documentation only
# - feat:      New feature
# - fix:       Bug fix
# - perf:      Performance improvement
# - refactor:  Code change without behaviour change
# - revert:    Revert a previous commit
# - style:     Formatting (whitespace, comments)
# - test:      Adding or updating tests

# Common Scopes:
# - alias:     Shell aliases
# - core:      Core config or logic
# - env:       Environment variables
# - func:      Shell functions
# - git:       Git configuration

# Commit Keywords:
# - add:       Introduce new content
# - clean:     Simplify or remove unused code
# - disable:   Turn off a setting or feature
# - document:  Improve comments or documentation
# - enable:    Turn on a setting or feature
# - fix:       Correct broken or buggy behaviour
# - format:    Adjust spacing or formatting
# - move:      Relocate items
# - refactor:  Restructure without changing behaviour
# - remove:    Delete or deprecate
# - rename:    Rename items
# - update:    Modify existing content

# Optional Body (wrap at 72 characters):
# - Explain what and why, not just how
# - Provide context for future maintainers
# - Link related issues or tickets

# Optional Footer:
# - Closes #123
# - Co-authored-by: <name> <email>

Configure Git to use the template:

bash
git config --global commit.template ~/dotfiles/.gitmessage

Verify Git configuration:

bash
git config --list

Press q to exit.

Commit Files #

Navigate to dotfiles directory:

bash
cd ~/dotfiles

Stage all changes:

bash
git add .

This stages all new, modified, and deleted files in the current directory and its subdirectories, excluding files listed in .gitignore.

Check status:

bash
git status

Review the files staged for commit and any untracked files.

Commit changes:

bash
git commit -m "Initial commit"

Create a commit with a descriptive message.

Step 4: Set Up GitHub Repository #

Create and push repository with GitHub CLI:

bash
gh repo create <user>/dotfiles --private --source=. --remote=origin --push

Explanation:

  • --private: Create a private repository. Use --public to make it public.
  • --source=.: Use the current directory as the repository source.
  • --remote=origin: Set remote name to origin (default).
  • --push: Push current local commits to the remote repository.

Step 5: Set Up Git Aliases (Optional) #

Aliases allow you to manage your dotfiles from anywhere, without needing to cd into the ~/dotfiles directory.

Edit alias file:

bash
vim ~/dotfiles/.aliases

Add:

~/dotfiles/.aliases
# Dotfiles

alias dotfiles='git --git-dir=$HOME/dotfiles/.git --work-tree=$HOME/dotfiles'
alias df_add='dotfiles add .'
alias df_commit='dotfiles commit'
alias df_pull='dotfiles pull'
alias df_push='dotfiles push'
alias df_status='dotfiles status'

Notes:

  • --git-dir=$HOME/dotfiles/.git: Points Git to the repository's .git folder.
  • --work-tree=$HOME/dotfiles: Restricts Git to track only files within ~/dotfiles/.
  • Benefit: These aliases let you commit, pull, push, or check status of your dotfiles without changing directories.

Reload shell configuration to apply changes

For Bash:

bash
. ~/.bashrc

For Zsh:

bash
source ~/.zshrc

Test alias:

bash
df_status

This runs git status inside the ~/dotfiles repo from anywhere, confirming the setup works.

Step 6: Clone Repository #

You only need to run this command once when setting up the repository on a new machine or server.

On remote server or new machine, run:

bash
git clone [email protected]:<user>/dotfiles.git ~/dotfiles

This clones your dotfiles repository into the ~/dotfiles directory, ready for use.

Step 7: Pull Latest Changes #

When your GitHub repository is updated, fetch and merge the latest changes locally by running:

bash
cd ~/dotfiles
git pull

This keeps your local copy in sync with the remote repository.