Published on 2020-11-12 by Nimai Patel
A few months ago I came across this
[ article ](https://www.atlassian.com/git/tutorials/dotfiles)
which explained how a bare git repository can be used to backup
dotfiles in the \*NIX home directory. I messed around with it for a while
and finally ended up with a no-nonsense system for managing system dotfiles.
A bare git repository is almost like a regular git project that you might create
with `git init`. The only difference is that it doesn't have a specific
working tree but _only_ the actual git repo
(i.e. the .git folder).
# Step One: Initializing the git repository
This is as simple as running the commands:
```
$ mkdir "${XDG_CONFIG_HOME}/cfg"
$ git init --bare "${XDG_CONFIG_HOME}/cfg/.git/"
```
If you've used git for any period of time then you know that the `git init`
command initializes an empty repository in the folder that you're currently in.
Since we want to create a bare repository, we pass the `--bare` flag and the
location of the git folder. This should create a `.git` folder in
`~/.config/cfg`. If you inspects its contents you'll find that they are similar
to any other repository's `.git` folder.
# Step Two: Accessing the repository via an alias/function
Add the following line to your .zshrc or .bashrc along with the rest of your
aliases:
```
cfg() { git --git-dir="${XDG_CONFIG_HOME}/cfg/.git/" --work-tree="$HOME" "$@" ; }
```
This function will allow us to stage and commit files to our backup repository.
The `--git-dir` flag specifies the git repository we made in step one and
`--work-tree` will allow us to track any file in our `$HOME` directory
using the repo.
# Step Three: Ignoring files we don't want to backup
Run `exec $SHELl` or restart your terminal to make the alias we made in the
previous step available. Then, run the following command, so that the
repository doesn't display the hundreds of files in your home directory every
time you check it's `status`:
```
$ cfg config --local status.showUntrackedFiles no
```
# Step Four: Setup a remote repository
Create an empty remote repository (I will be using GitHub) and get its SSH or
HTTP. On GitHub this is immediately available after the repo is created.
Finally add the remote with:
```
$ cfg remote add origin
```
At this point you can simply do something like:
```
$ cfg add ~/.vimrc
$ cfg commit -m "Adding .vimrc"
$ cfg push origin master
```
This will make the repository start tracking your .vimrc and you can commit
and push the file to GitHub. Pretty much all git commands like `status` and
`diff` should now be available to you with the `cfg` function.
# Getting your dotfiles on a new system:
Now all you have to do on a new system is run the following commands
and you'll have all your settings back:
```
git init --bare "${XDG_CONFIG_HOME}/cfg/.git/"
cfg() { git --git-dir="${XDG_CONFIG_HOME}/cfg/.git/" --work-tree="$HOME" "$@" ; }
cfg config --local status.showUntrackedFiles no
cfg remote add origin https://github.com/nimaipatel/dotfiles.git
cfg pull origin master
```
You might get some errors if you already have, say, a .zshrc in your new
system. In this case you probably would want to delete this before pulling
your files from the remote.
That's it we're done 🥳. Please do tell me if you face any issues with the
script, in case you use it!