Necoro’s Blog

Blog? Blog? There is no blog…

Managing your configuration files with Git and StGit

with one comment

This is propably a wide known problem: You want your personal config files (for ViM, Emacs, $SHELL, …) on all the boxes you have to deal with. The solution here is often: Use some distributed VCS/SCM like git, bzr, hg, whatever and be happy. But it might happen (and it will surely happen quite often), that the boxes have different versions installed for some packages. Or there are other differences (for example: I have to use other font sizes on my laptop than on my PC). This not a problem, if the config files you are using allow importing other ones — you have your global options and override them with some local additions. Well, unfortunately, this is not always supported (e.g. I do not know of a way to import something into .gitconfig). So we have to find a solution…

And I guess, I found one: Use Git to manage the global stuff — and use StGit to manage a stack of patches for the local boxes :)

Note: As I am personally using the zsh, I will talk of the .zshrc. Adopt it to fit your personal shell. Additionally, I’ll assume, that you know how to use git.

1. Creating the global configuration repository

First remark: This idea is to 99% based on this post I found. I’ll repeat it here nevertheless.

  1. Create an initial directory to store the git data:
    mkdir ~/.config.git
  2. Create an alias for managing this special git repository:
    alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'
  3. Initialize the git repo:
    config init
  4. (Optional) To have your config status calls and similar not being cluttered with everything in your home directory, make git ignore everything :)
    echo "*" >> .gitignore

    Note that you now have to use config add -f to add files, because the “add” command will not add ignored files by default.

  5. Add all the files you want to have managed to the reposority using config add -f. Do not forget the .gitignore, if you’ve done the step above.
  6. Finally: Commit
    config commit
  7. (Optional, but suggested) Push your reposority to somewhere, where you access it from all the boxes needed. If you push to a public host: Take care, that there is no sensible information contained in your configs, like passwords or similar.

    config remote add origin
    config push origin

2. Initializing StGit

Note: A general StGit tutorial can be found here:
Note #2: All the following commands should be done in your home directory, because the/my current StGit version (0.14.3) seems not to handle such a strange setup :).

  1. Yet another alias:
    cstg='GIT_DIR=$HOME/.config.git stg'
  2. Initialize your repo for cstg:
    cstg init
  3. Add your local settings as StGit patches:
    cstg new some-cool-new-change
    # ... hack ...
    cstg refresh
    cstg new yet-another-change
    # ... hack....
    cstg refresh
    # ...

3. Modify your global settings

As StGit manages your patches as git commits, you cannot simply use git/config to modify the global settings. This would take your already applied patches and safe them in the history. Thus I will show, how to deal with it. As the example task: Add the two aliases we defined to .zshrc.

New method (needs stgit-0.15)

  1. Create a new patch:
    cstg new "temp-patch"
  2. Do your change:
    for i in cstg config; echo $(alias $i) >> ~/.zshrc
  3. Refresh:
    csgt refresh
  4. Commit to git:
    cstg commit "temp-patch"
  5. Optional:Push to remote.
    config push
    cstg push -a

    Note If you do not want to push to the remote, you still need to do

    cstg push -a

I created a zsh-function for the complete procedure. You can find it here (the function “cci”).

Old method (prior to stgit-0.15)

  1. Get rid of the current local patches:
    cstg pop -a

    Note: Use cstg pop -ak if you already made your changes

  2. Do your change:
    for i in cstg config; echo $(alias $i) >> ~/.zshrc
  3. Commit:
    config commit -a .zshrc
  4. Push:
    config push
  5. Reapply patches:
    cstg repair
    # I haven't yet found out if this repair command 
    # is really necessary always... 
    # it seems to work without, so far
    cstg push -a

4. Cloning on other hosts

  1. Clone the repository. Example:
    git clone
  2. Move the .git directory to its final destination.
    mv dotfiles/.git ~/.config.git
  3. Get your old configs out of the way and make sure, that you have a backup of your local settings.
  4. Copy your settings into the wild :). (Note that I use copy instead of move, as I have sometimes only parts of directories managed.)
    cp -r dotfiles/.* ~
    # also copy dotfiles/* if you have non-dotted stuff
  5. Remove the dotfiles directory
  6. Open another shell or re-login, so your new settings (especially the aliases) are loaded.
  7. cstg init
  8. Create your local patches

5. Conclusion

I have just “developped” this approach today (I think, there were already other guys having this idea :) – but I could not find something using a quick google search). So it really needs some testing to see if everything works out as expected. And a nice wrapper script should also be written to ease the work. Ideally you would only need config and not two different commands.

So — I’m going to test this on a couple of boxes and we’ll see where this ends :D.

Update I am currently thinking, whether a setup using only branches and using rebasing could achieve the same but being easier to manage. I have to test it :)


Written by Necoro

October 8, 2009 at 01:52

One Response

Subscribe to comments with RSS.

  1. […] Git. Revisited. I showed a way of managing the configuration files with git and StGit in the post two days ago. But this has two […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: