Photo by Roman Synkevych 🇺🇦 on Unsplash
If you have been using Linux for a while, you may have tried ‘distro hopping’. After some time, it begins to be a pain as you try to configure your new distro just the way you like it. If you’re like me who has a ton of applications installed, you’ll relate to having hours or even days spent crafting your system to your liking.
I have stumbled upon a video by Distrotube showing how he manages his dotfiles using a git bare repository and I have decided to try it our myself.
Why use git bare?
Here are some advantages in using this technique.
- No extra tools required!
- You only need
git
for this to work. Sincegit
is pretty much installed by default in most distros, you’d be pretty much set-up already. - No need to deal with symlinks.
- One way you can control your dotfiles is if you place them in a folder and send out symlinks to the correct places where your dotfiles are expected to be placed. This is a bit cumbersome especially if you have a lot of configuration files to handle. You can most certainly set up a script to do this for you though.
- Your files are placed in version control.
- You can track changes made in your dotfiles, use different branches if you want to try out a completely different configuration, clone your dotfiles to a new machine or a new installation to replicate what you have in another system, and revert back to a previous configuration. This is all built-in with
git
.
How does this work?
This is pretty much how you would use git
. You can use the same commands for adding files, removing files, staging, committing, and pushing them to a remote repository.
What’s different is that we’ll be using a Git bare repository
. This is basically like the .git
hidden directory in your normal git repositories. An alias will be used in order for our commands so that it will not interfere with any other local git repositories.
Getting started
We’ll start by initializing a git bare repository
.
git init --bare $HOME/.cfg
Change .cfg
to any name you wish. This is just an arbitrary name for our repository.
Define an alias for the command. You can also use any other alias that you would want. This is for brevity only. We don’t want typing lengthy commands everytime!
alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
Run this next command to hide all files that we are not explicitly keeping track of.
config config --local status.showUntrackedFiles no
Add the alias to your .bashrc
or .zshrc
or config.fish
for convenience. You can also run this command to save you time.
echo "alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'" >> $HOME/.bashrc
And that’s it! You have successfully set up your git bare repository
. You can pass git
commands to your alias and add your dotfiles and other configurations. Of course, this is not limited to just dotfiles. You can add all kinds of files and directories here.
config status
config add .bashrc
config commit -m "Add bashrc"
config push
Cloning your previous configurations to your new installation
So you have decided to do a clean install of your operating system and you want to have it configured fast. Your git repository
is here and ready to settle in your new system.
Set up your alias before starting. You may just type it in your terminal or add it to your .bashrc
, .zshrc
, config.fish
.
alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
Add your git bare repository to a .gitignore
file. This will help you avoid any recursion problems.
echo ".cfg" >> .gitignore
Again, .cfg
is an arbitrary directory name. You can use any folder name you wish.
You’re now ready to clone your dotfiles into a git bare
repository. Take note that you will need to use your the directory you specified in the previous step, replacing the .cfg
directory in this command.
git clone --bare <git-repo-url> $HOME/.cfg
Make sure that your alias is defined in your current shell scope. If you have the alias in your .bashrc
, .zshrc
, or config.fish
, you may need to source
them again for the alias to take effect.
alias config='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
OR
source .bashrc
Checkout the contents of your bare repository
to your $HOME
directory.
config checkout
Of course, this command might fail as you might have similarly named files already in your new installation. You may see errors such as the one below.
error: The following untracked working tree files would be overwritten by checkout:
.bashrc
.gitignore
Please move or remove them before you can switch branches.
Aborting
There is a solution mentioned in an article in Atlassian written by @durdn. It involves backing up the files using a shell script. I think this is an elegant and efficient way for backing up files causing the checkout error.
mkdir -p .config-backup && \\\\
config checkout 2>&1 | egrep "\\\\s+\\\\." | awk {'print $1'} | \\\\
xargs -I{} mv {} .config-backup/{}
After running the above, run the checkout command again.
config checkout
Once you run config status
, you may see a lot of untracked files again. Let’s set the showUntrackedStatus
flag to no
again so we’ll only see files which we only explicitly track.
config config --local status.showUntrackedFiles no
Your set up is now complete and you can now add and update files using your config
alias and git
commands.
config status
config add .bashrc
config commit -m "Add bashrc"
config push
This setup may be a bit confusing at first but once you get the hang of it, then you’ll see how simple it really is.