Managing your configuration files with Git and StGit
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.
- Create an initial directory to store the git data:
mkdir ~/.config.git
- Create an alias for managing this special git repository:
alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'
- Initialize the git repo:
config init
- (Optional) To have your
config statuscalls and similar not being cluttered with everything in your home directory, make git ignore everything :)echo "*" >> .gitignore
Note that you now have to useconfig add -fto add files, because the “add” command will not add ignored files by default. - 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. - Finally: Commit
config commit
- (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.
Example:
config remote add origin git@github.com:Necoro/dotfiles.git config push origin
2. Initializing StGit
Note: A general StGit tutorial can be found here: http://www.procode.org/stgit/doc/tutorial.html
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 :).
- Yet another alias:
cstg='GIT_DIR=$HOME/.config.git stg'
- Initialize your repo for cstg:
cstg init
- 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)
- Create a new patch:
cstg new "temp-patch"
- Do your change:
for i in cstg config; echo $(alias $i) >> ~/.zshrc
- Refresh:
csgt refresh
- Commit to git:
cstg commit "temp-patch"
- Optional:Push to remote.
config push cstg push -a
Note If you do not want to push to the remote, you still need to docstg 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)
- Get rid of the current local patches:
cstg pop -a
Note: Usecstg pop -akif you already made your changes - Do your change:
for i in cstg config; echo $(alias $i) >> ~/.zshrc
- Commit:
config commit -a .zshrc
- Push:
config push
- 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
- Clone the repository. Example:
git clone git@github.com:Necoro/dotfiles.git
- Move the .git directory to its final destination.
mv dotfiles/.git ~/.config.git
- Get your old configs out of the way and make sure, that you have a backup of your local settings.
- 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
- Remove the dotfiles directory
- Open another shell or re-login, so your new settings (especially the aliases) are loaded.
cstg init
- 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 :)
[...] 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 [...]
Managing your configuration files with Git. Revisited. « Necoro’s Blog
October 10, 2009 at 02:26