# Manage Dotfiles with Git

I'm managing my dotfiles with git. My method serves me well for a few
years already and so I think it's time to write it down.

If you think git, you might think of a dotfile repository and dozens of
symlinks into the home directory. This is precisely what kept me from
using git until I discovered bare repositories.

Create your dotfile repository with the `--bare` parameter

```
git init --bare $HOME/.cfg
```

This creates only a folder for git control files, which normally reside
inside the .git folder within the repository.

You can now tell git to use $HOME as your work-tree directory. This
makes git handle your home directory like all the files would be within
the git repository. Now you can:

```
git --git-dir=$HOME/.cfg/ --work-tree=$HOME add .vimrc
git --git-dir=$HOME/.cfg/ --work-tree=$HOME commit -m "my .vimrc"
```

If course it is silly to type out such a long command every time you
want to interract with your dotfiles. So why not create an alias?

```
alias config='git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
```

Put this in your .bashrc or .kshrc and you can now use the command
"config" in the same way you usually use git.

```
config add .vimrc
config commit -m "my vimrc"
```

Maybe you were brave and typed config status already. This will list
the content of your whole home directory as "untracked files". This is
not what we want. We can run git config and tell it to stop doing
this. But of course we must run our git, which is called `config`.

```
config config --local status.showUntrackedFiles no
```

Now git status will only check what's being tracked. So if you add your
vimrc file and later change it, "config status" will show it, "config
diff" will diff it...

You can now use the power of git with your new "config" command.

Well okay, and because I'm lazy and don't want to think about git commit
messages, I'm using this to push my changes:

```
dotfiles_autoupdate() {
    config add -u && \
    config commit -m "Update $(date +"%Y-%m-%d %H:%M") \
        $(uname -s)/$(uname -m)-$(hostname -s)" && config push
}
```

This command takes all changed files and commits them with the date and
some machine information. Not creative, but I don't care. YMMV.

Setting up the dotfiles on a new system can also be automated with this
function:

```
dotfiles_init() {
    git --no-replace-objects clone --bare --depth 1 \
        sdk@git.server.de:dotfiles.git $HOME/.cfg;
    config config --local status.showUntrackedFiles no;
    config checkout -f
}
```

There you have it. Now you can use the full power of git directly in your home
directory by using the new "config" command instead of git. You can "config
status/add/rm/branch/rebase/pull/push" as you wish and there's no additional logic
necessary (like symlinks to watch out for).

I'm maintaining a "work branch" on top of my "main" (private) branch.
This work branch even has a different upstream (corporate git repository
at work). But I'm still able to access changes I made to my private git
repository and merge them as I like (or vise versa).
* 2023-11-06: 
