I want to store all my dotfiles in git
repository with separate branch
for each machine. I have a problem I can't solve that blocks me from
using git
for that purpose. I'd like to know how other people
solved it.
I'm going to have a single master
branch which contains only
template definitions and definitions which are supposed to be common
for all branches, for example:
export EMAIL="@EMAIL@"
export SURFRAW_google_results=1000
I will replace @EMAIL@
with my correct e-mail on machine branches
and commit it but SURFRAW_google_results
will stay the same. For
example, on work
branch I'll have this:
export EMAIL="[email protected]"
export SURFRAW_google_results=1000
Now, I decided to change SURFRAW_google_results=1000
to 10. It's
supposed to be shared globally, so I first I change it on master
:
export EMAIL="@EMAIL@"
export SURFRAW_google_results=10
and then on I rebase work
onto master
:
$ git checkout work
$ git rebase master
And now I get conflict because the line that is above the line I changed is different:
<<<<<<< a60114eea1c98d2354a07bd4fd0cdd63cba62e93
export EMAIL="@EMAIL@"
export SURFRAW_google_results=10
=======
export EMAIL="[email protected]"
export SURFRAW_google_results=1000
>>>>>>> m
In case of bash
I could quickly get away with
including a machine-specific part by sourcing mechanism but how about
configs that do not support including/sourcing other configs such as .fluxbox/keys
or .screenrc
?
Instead of modifying concurrent data directly between branches (which results in conflict as illustrated in this answer), you can considering content filter driver, using .gitattributes declaration.
(image from "Customizing Git - Git Attributes", from "Pro Git book")
The idea is to manage those dotfiles in version, but with template placeholders in place of the actual values (which depends on the branch).
The generated actual dotfiles remains ignored (by the .gitignore
).
That means your actual working tree does not get "dirty".
The files with the actual values can also be versioned, but with different names (so no conflicts when merging/rebasing)
The smudge script select the correct value file depending on the branch name, and generate the correct dotfile based on the dotfile template the smudge script is applied on during a git checkout
.
To have a smudge acting differently per branch, I would recommend calling a script which starts by looking the name of the current branch.
See an example in my older answer "Best practice - Git + Build automation - Keeping configs separate".
#!/bin/sh
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
The OP mentions that, for the smudge script to apply on checkout, removing the index is needed. That is true, as I explained here:
the index is the middle-man for moving things from your work-tree to the object-store AND for moving things from the object-store to your work-tree.
By removing the index, you force git to restore it, which means applying any content filter driver if present.
See "git: re-checkout files after creating smudge filter".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With