Dotfiles

User-specific application configuration is traditionally stored in so called dotfiles (files whose filename starts with a dot). It is common practice to track dotfiles with a version control system such as Git to keep track of changes and synchronize dotfiles across various hosts. There are various approaches to managing dotfiles (e.g. directly tracking dotfiles in the home directory v.s. storing them in a subdirectory and symlinking/copying/generating files with a shell script or a dedicated tool). Apart from explaining how to manage dotfiles this article also contains a list of dotfile repositories from Arch Linux users.

Tracking dotfiles directly with Git

The benefit of tracking dotfiles directly with Git is that it only requires Git and does not involve symlinks. The disadvantage is that host-specific configuration generally requires merging changes into multiple branches.

The simplest way to achieve this approach is to initialize a Git repository directly in your home directory and ignoring all files by default with a gitignore(5) pattern of *. This method however comes with two drawbacks: it can become confusing when you have other Git repositories in your home directory (e.g. if you forget to initialize a repository you suddenly operate on your dotfile repository) and you can no longer easily see which files in the current directory are untracked (because they are ignored).

An alternative method without these drawbacks is the "bare repository and alias method" popularized on Ask Hacker News: What do you use to manage your dotfiles?, which just takes three commands to set up:

$ git init --bare ~/.dotfiles
$ alias dotfiles='/usr/bin/git --git-dir="$HOME/.dotfiles/" --work-tree="$HOME"'
$ dotfiles config status.showUntrackedFiles no
Note: Usually one's dotfiles all have default permissions, but if specific file permissions for some files are a must, another approach should be used, as git does not store permissions (Discussion)

Your dotfiles can be replicated on a new system like:

$ git clone --bare <git-repo-url> $HOME/.dotfiles
$ alias dotfiles='/usr/bin/git --git-dir="$HOME/.dotfiles/" --work-tree="$HOME"'
$ dotfiles checkout
$ dotfiles config --local status.showUntrackedFiles no
  • In case of already having some stock dotfiles which might get overwritten, you'll encounter something similar to the following the error:
$ dotfiles checkout
error: The following untracked working tree files would be overwritten by checkout:
    .bashrc
    .gitignore
Please move or remove them before you can switch branches.
Aborting
You could use $ dotfiles checkout -f which will rewrite the already existing files, or in a safer approach take a backup of all the files with the following script and then using checkout:
mkdir -p .dotfiles-backup && \
dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | \
xargs -I{} mv {} .dotfiles-backup/{}

You can then manage your dotfiles with the created alias. If you are using Bash and would like bash completion for this alias, simply install bash-complete-aliasAUR, then add the alias and the following line to your ~/.bashrc.

$ complete -F _complete_alias dotfiles

Another way to get completion in bash is adding the following to your ~/.bashrc (taken from ):

source /usr/share/bash-completion/completions/git
__git_complete dotfiles __git_main
Tip: To avoid accidentally committing confidential information, see Git#Filtering confidential information.

Host-specific configuration

A common problem with synchronizing dotfiles across various machines is host-specific configuration.

With Git this can be solved by maintaining a master branch for all shared configuration, while each individual machine has a machine-specific branch checked out. Host-specific configuration can be committed to the machine-specific branch; when shared configuration is modified in the master branch, the per-machine branches need to be rebased on top of the updated master.

In configuration scripts like shell configuration files conditional logic can be used. For example, Bash scripts (i.e. .bashrc) can apply different configuration depending on the machine name (or type, custom variable, etc.):

if [[ "$(hostname)" == "archlaptop" ]]; then
    # laptop specific commands here
else
    # desktop or server machine commands
fi

Similar can also be achieved with .Xresources.

If you find rebasing Git branches too cumbersome, you may want to use a tool that supports file grouping, or if even greater flexibility is desired, a tool that does processing.

Tools

File grouping
How configuration files can be grouped to configuration groups (also called profiles or packages).
Processing
Some tools process configuration files to allow them to be customized depending on the host.
NamePackageWritten inFile groupingProcessing
dotbot dotbotAURPythonconfiguration fileNo
chezmoi chezmoiGodirectory-basedGo templates
dot-templater dot-templater-gitAURRustdirectory-basedcustom syntax
toml-bombadil toml-bombadilRustconfiguration filetera
dotdrop dotdropAURPythonconfiguration fileJinja2
dotfiles dotfilesAURPythonNoNo
dotter dotter-rsAURRustconfiguration fileHandlebars
dt-cli dt-cliAURRustconfiguration fileHandlebars
GNU Stow stowPerldirectory-basedNo
Mackup mackupAURPythonautomatic per applicationNo
mir.qualia mir.qualiaAURPythonNocustom blocks
rcm rcmAURShelldirectory-based (by host or tag)No
yas-bdsm Shelldirectory-basedNo

Tools wrapping Git

If you are uncomfortable with Git, you may want to use one of these tools, which abstract the version control system away (more or less).

NamePackageWritten inFile groupingProcessing
dotbare dotbareAURShell (fzf)repository-wiseNo
dotgit dotgitAURPythonfilename-basedNo
homeshick homeshick-gitAURBashrepository-wiseNo
homesick Rubyrepository-wiseNo
Pearl pearl-gitAURPythonrepository-wiseNo
vcsh vcshShellrepository-wiseNo
yadm(1) yadmShellfilename-based
(by class/OS/distro/hostname/user)
Built-in templates/Jinja2/ESH
(optional)
dfm dfmAURPerlrepository-wiseNo
  1. Supports encryption of confidential files with GPG or OpenSSL.

User repositories

Note: This table is used as a reference/examples of dotfiles, if you are submitting your dotfiles to the table, please ensure they are kept clean, commented and up to date.
Warning: These dotfiles have not been verified by any of the Arch Linux staff, use at your own risk.
AuthorShell (Shell framework)WM / DEEditorTerminalMultiplexerAudioMonitorMailIRCFile ManagerRSS reader
adamperkowski zshdwmNeovimsttmuxmpvcustomWeeChat
ananthu ZshbspwmNeovimAlacrittyMpvhtop, PolybarNeomuttWeeChatRanger
ayekat ZshkaruiwmVimRxvt-unicodetmuxncmpcpp/MpdkaruibarMuttIrssi
bachoseven ZshDwm sourceNeovimSt sourcetmuxncmpcppbottomNeomuttWeeChatLfnewsboat
bamos Zshi3/xmonadVim/Emacsrxvt-unicodetmuxmpv/cmusconky/xmobarmuttERC
brisbin33 zshxmonadvimrxvt-unicodeGNU Screendzenmuttirssi
christian-heusel Zshi3Neovimst / terminatorbyobu / tmuxhtopneomutt/ThunderbirdWeeChatnemo / ranger
CuterThanYou Zshi3 / HyprlandNeovimAlacritty / FootMpvPolybar / YambarLf / ThunarNewsboat
dikiaap Zshi3-gapsNeovimAlacrittytmuxi3blocksnnn
Earnestly Zshi3/orbmentVim/EmacstermitetmuxmpdconkymuttWeeChat
egnrse Zsh/BashHyprlandNeovimAlacrittyVLCbottomDolphin
ErikBjare Zshxmonad/Xfce4Vimterminatortmuxxfce4-panelWeeChat
erikw Zsh/Bashdwm/macOSNeovimurxvtctmuxmpdmuttirssi
filiparag fishbspwmVimAlacrittytmuxmpv, playerctlhtop, Polybarmail-notificationPCManFM
Freed-Wu zshopenboxNeovimweztermtmuxcmusbottomneomuttWeeChatNeovimnewsboat
graysky ZshXfceVimterminalncmpcppcustomThunderbird
hugdru ZshawesomeNeovimrxvt-unicodetmuxThunderbirdWeeChat
insanum BashHerbstluftwmVimevilvtetmuxdzenmutt-kz
isti115 pwsh sway neovim alacritty tmux mpv / playerctl waybar / htop / ytop ranger
jasonwryan Bash/ZshdwmVimrxvt-unicodetmuxncmpcppcustommuttirssi
jdevlieghere ZshxmonadVimterminaltmuxhtopmuttWeeChat
jelly Zshi3Vimtermitetmuxncmpcppmutt-kz-gitWeeChat
jl2 Zshswayfxgeanyfootmissioncenter, eww (bar)srainthunar
karras ZshWayfireNeovimTerminatorWaybar
MarkusZoppelt ZshGNOMENeovimAlacrittytmux
maximbaz ZshSwaykakounekittywaybarneomuttnnn
neersighted fishi3NeovimAlacrittytmuxncmpcpp
nimaipatel fishawesomeNeovimAlacrittyncmpcpp
oibind fishawesomeNeovimsttmuxhtop-vimWeeChatlf
orhun Bashi3-gapsNeovimAlacrittyi3statusWeeChattere
patri9ck ZshbspwmVimkittyThunar
peterzuger Zshi3-gapsEmacsrxvt-unicodeGNU Screenmochtop
polyzen Zshi3NeovimAlacrittytmuxmpvi3status,htophimalayarangerNewsboat
potamides BashawesomeNeovimtermitetmuxncmpcppconky,htopmuttWeeChatranger
sistematico zsh/fish/bashi3-gapsVim/nanotermitetmuxncmpcppPolybarmuttWeeChat
thecashewtrader EshellEXWMEmacsEmacs (VTerm)EmacsBongohtopmu4eERCDiredElfeed
thiagowfx bash/zshi3VimAlacrittytmuxplayerctli3statusranger
tplasdio bash (ble.sh)awesomeneovimalacrittytmuxmpv, mpvshtopneomuttweechatlf
tuurep BashopenboxNeovimAlacrittytmuxPolybar
unrealapex ZshdwmNeovimStncmpcpphtopNeomuttIrssifffNewsboat
w0ng ZshdwmVimrxvt-unicodetmuxncmpcppcustommuttirssi
whitelynx fishi3Neovimkittyi3pystatus
whynothugo ZshSwayNeovimAlacrittympvwaybar, topneomuttNemo

See also

This article is issued from Archlinux. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.