/HOME/                                           /prev/ /Hotline Webring/ /next/


Dotfiles Management                                                   2026-08-02
________________________________________________________________________________

This guide describes how I manage my dotfiles. It is heavily inspired by Drew
DeVault's approach, but I have adapted it over the years to better suit my own
workflow.

Drew's blog on dotfiles: https://drewdevault.com/2019/12/30/dotfiles.html

--- [001] Setup Options --------------------------------------------------------

 In this setup, the $HOME directory is a Git repository. This guide assumes you
 are starting with an empty $HOME and have basic familiarity with operating a
 UNIX-like system. On a real system you would typically move existing files out
 of the way first, or use an existing repository as described below.

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ cd $HOME; git init                                                       |
 |                                                                            |
 +----------------------------------------------------------------------------+

 Alternatively, you can use an existing repository. This is preferable if you
 already have dotfiles backed up using this or a similar layout and want to
 deploy them to a new environment. A plain git clone refuses to write into a
 directory that is not empty, so initialise the repository in place and fetch
 into it instead:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ cd $HOME                                                                 |
 | $ git init                                                                 |
 | $ git remote add origin https://codeberg.org/pigeon/dotfiles               |
 | $ git fetch origin                                                         |
 | $ git checkout -f master                                                   |
 |                                                                            |
 +----------------------------------------------------------------------------+

 The -f option overwrites any local files that clash with tracked ones, so back
 up anything you care about first.

 In practice, I always use my existing dotfiles repository on a new machine.
 The git init route above is there to teach the underlying idea, as you will
 only ever run it once: the first time you start tracking your dotfiles.


--- [002] Ignore Everything by Default -----------------------------------------

 By default this setup would track every file in your $HOME directory. To avoid
 this, add a rule that ignores everything unless it is explicitly tracked. Do
 this straight after creating the repository:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ echo "*" >> $HOME/.git/info/exclude                                      |
 |                                                                            |
 +----------------------------------------------------------------------------+

 I find this better than a .gitignore file in the root of the repository, as
 that would be one extra file polluting /home/$USER/


--- [003] Adding Dotfiles ------------------------------------------------------

 I do not limit this to shell and editor configs. Pretty much anything
 config-related gets tracked this way, including River, Kakoune and whatever
 else I have tweaked. If it is a file I would be annoyed to lose or retype on a
 new machine, it goes in.

 Force-add the files you want to track:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git add -f .bashrc                                                       |
 | $ git commit -m "initial commit"                                           |
 |                                                                            |
 +----------------------------------------------------------------------------+

 If you started with git init, point the repository at your remote and push for
 the first time:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git remote add origin https://codeberg.org/pigeon/dotfiles               |
 | $ git push -u origin HEAD                                                  |
 |                                                                            |
 +----------------------------------------------------------------------------+

 Repeat for other files:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git add -f .config/river/config                                          |
 | $ git add -f .config/kakoune/kakrc                                         |
 | $ git add -f .profile                                                      |
 | $ git commit -m "add more files"                                           |
 | $ git push                                                                 |
 |                                                                            |
 +----------------------------------------------------------------------------+

 I also use shell scripts to track things related to / or the root user. One
 automatically backs up a list of my manually installed packages to
 $HOME/.local/packages, and another does the same for my init services and user
 groups. This is handy for backing up system-level settings on a single-user
 system.


--- [004] Hiding Files ---------------------------------------------------------

 I mainly use this for README and LICENSE. I want them visible when browsing
 the repository on Codeberg, but they have no reason to sit in $HOME cluttering
 things day to day.

 For files you want Git to ignore locally:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git update-index --assume-unchanged README LICENSE                       |
 | $ rm README LICENSE                                                        |
 |                                                                            |
 +----------------------------------------------------------------------------+

 Check hidden files:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git ls-files -v | grep "^h"                                              |
 |                                                                            |
 +----------------------------------------------------------------------------+

 Restore them later:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git update-index --no-assume-unchanged README LICENSE                    |
 | $ git restore README LICENSE                                               |
 |                                                                            |
 +----------------------------------------------------------------------------+


--- [005] Untracking a File Without Removing It --------------------------------

 Sometimes you want Git to stop tracking a file but keep it sitting in $HOME
 exactly as it is, with no deletion involved. This is different from hiding a
 file with assume-unchanged, since that keeps the file tracked and just tells
 Git to stop checking it for changes. Untracking actually removes it from the
 repository's index while leaving the file on disk untouched.

 Untrack a file, keeping it in the working tree:

 +----------------------------------------------------------------------------+
 |                                                                            |
 | $ git rm --cached .bashrc                                                  |
 | $ git commit -m "untrack .bashrc"                                          |
 | $ git push                                                                 |
 |                                                                            |
 +----------------------------------------------------------------------------+


--- [006] Final Thoughts -------------------------------------------------------

 That is the whole method: a $HOME repository, everything ignored by default,
 and files force-added one at a time as you decide they are worth tracking. It
 does not require extra tooling such as stow, and it scales fine whether you
 are tracking three files or thirty. I prefer this over the popular
 bare-repository approach because it behaves like a normal Git repository,
 requires no shell aliases and works with standard Git commands.

 If you want to see it in practice rather than just in theory, my own dotfiles
 are public and follow this exact layout:

 https://codeberg.org/pigeon/dotfiles

________________________________________________________________________________


Flockless (C) 2021-2026 by Joseph is licensed under CC BY-SA 4.0