- Context
- Create a dotfiles github repo
- Organise your stuff
- Think about the install script
- Working with sub-repos
- Conclusion
Context
There are plenty of github dotfiles framework on github dotfiles They are complicated and I don’t want to add commands or aliases that I don’t actually master. This is for like minded person that I write this tutorial
Create a dotfiles github repo
It’s pretty straightforward and this tutorial isn’t about git so. If you don’t feel comfortable with it just take a look at the awesome github doc
Organise your stuff
Basically I need to store on github only my .bashrc
and vim configuration files.
Including plugins.
The easier way to do it is maybe to store everything as it is stored on my /home
in the repo.
The install script will then symlink the repo’s content to my /home
.
Repo organisation
| .
repo_root
|_install.sh
|_dotfiles
|_.bashrc
|_.inputrc
|_.vimrc
|_.vim
|_ bundle
|_ colors
|_ synthax
|_ ...
|
Content of .vim/bundle
should be subrepositories in order to always have under the hand the
latest plugins version.
We will see that in this article last chapter.
Think about the install script
I don’t want to change my install script each time I add a dotfile, a vim plugin or whatever. For my personnal purpose I think that a simple sequence like:
- Get latest change
git pull
- Eventually commit local changes
git push
- Resinstall everything
./install.sh
Will work great for my need.
Indeed ./install.sh
can make the git pull/push for me ;)
An exemple install script
| .
#!/bin/bash
echo 'Dotfiles - http://gustavepate.github.io/'
HOME_DIR=~ #For testing purpose
SYNC_ROOT=./dotfiles
SYNC_FILES=$SYNC_ROOT/*
SCRIPT_FULL_PATH=$(readlink -f $0)
REPO_PATH=$(dirname $SCRIPT_FULL_PATH)
echo $REPO_PATH
# If Git is not installed...
if [[ ! "$(type -P git)" ]]; then
sudo apt-get -qq install git
else
echo "git installed.....ok"
fi
#Command must be run from the repo root
if [ ! -e $SYNC_ROOT'/.bashrc' ]
then
echo "install must be execute from the repo root"
exit 1
else
echo "command run from secure path.....ok"
fi
#Pull latest change
git pull
#Symlink all files and directory in the dotfiles directory to the home folder
#allowi bash to find .dotfiles
shopt -s dotglob
#for all files and directory in the dotfiles directory
for f in $SYNC_FILES
do
# take action on each file. $f store current file name
echo "Processing $f file..."
#strip the left part
FILE=`basename $f`
#create /home equiv for repo file
H_FILE=$HOME_DIR'/'$FILE
#create backup path
TIMESTAMP=`date +%d%m%Y-%H%M%S`
H_FILE_BACKUP=$HOME_DIR'/'$FI'.'$TIMESTAMP'.bck'
echo "Checking $H_FILE"
#check equivalent in the homedir
#if a link, delete it
if [ -L $H_FILE ];then
rm $H_FILE
echo $H_FILE" rmed...........ok"
#if a dir or a file => mv
elif [ -e $H_FILE ]; then
echo $H_FILE" backuped...........ok"
mv $H_FILE $H_FILE_BACKUP
# weird
else
echo "WARNING: I don't know what to do with this file"
fi
#create a new link
ln -s $REPO_PATH'/'$f $H_FILE
echo $H_FILE' symlinked to '$REPO_PATH'/'$f
done
|
Working with sub-repos
For the moment, my git repo only contains clones of others repository.
Here are my needs: * I wan’t to automatically keep my vim plugins up-to-date. * On a fresh computer I don’t want to manually add all my vim plugins
One can use submodule or subtree.
__Edit 2013-08-13: __ giving up submodules
Submodule is the common way to go but they are a pain to delete.
I tried these a little before giving up. Indeed I was changing my vim plugins list quickly at this time and it was not a sustainable solutions. See the necessary steps to delete a submodule and you will agree with me ;)
So I tried to use subtree but my ubuntu 12.04 don’t come with the necessary git version. I gave up and stay with git clone for the moment.
For the record, you will find notes on the git subtree and git submodules below.
Conclusion
Et voilà ! Here is a link to my own github dotfiles repo where you can find the latest version of the install script I currently use. It took me a little more than a hour to make it working (including typing this article).
I hope this will help you !
Appendix I: Setup a subtree
Adding a remote
| git remote add -f minibufexpl.vim https://github.com/fholgado/minibufexpl.vim
|
Fetch a repo as a subtree
| git subtree add --prefix dotfiles/.vim/bundle/minibufexpl.vim minibufexpl.vim master --squash
|
Update a subtree
| git fetch minibufexpl.vim master
git subtree pull --prefix dotfiles/.vim/bundle/minibufexpl.vim minibufexpl.vim master --squash
|
Delete a subtree
| #TODO
|
Appendix II: Setup a submodule
I warn you about it subtrees have proven to be more relevant to my needs than submodule. But, anyway, here’s some submodule documentation if you need it.
Add a submodule
First add a submodule to your git repo:
| git submodule add https://github.com/tpope/vim-fugitive dotfiles/.vim/bundle/vim-fugitive
|
Run it without a trailing slash !
It clones https://github.com/tpope/vim-fugitive
in the directory dotfiles/.vim/bundle/vim-fugitive
| # OK: adds the submodule
git add local/path
# NO !!!! adds all the files in the submodule directly into your repository
git add local/path/
|
Then you can:
| $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: .gitmodules
# new file: dotfiles/.vim/bundle/vim-fugitive
|
Notice how the change log only show you the directory of the submodule without all its content.
Secure the submodule
Notice the .gitmodule
file.
Let’s take a look.
| [submodule "dotfiles/.vim/bundle/vim-fugitive"]
path = dotfiles/.vim/bundle/vim-fugitive
url = https://github.com/tpope/vim-fugitive
|
pretty straightforward hum ?
You can tweak in in order to ignore changes made by you in the submodules.
| [submodule "dotfiles/.vim/bundle/vim-fugitive"]
path = dotfiles/.vim/bundle/vim-fugitive
url = https://github.com/tpope/vim-fugitive
#ignore changes in the submodule while commiting
ignore = dirty
|
Untracked change
If, on commit, git notifies you with a Untracked Content Error
| # On branch master
# Changes not staged for commit:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory) # (commit or
# discard the untracked or modified content in submodules) #
# modified: bundle/snipmate
# (untracked content)
|
Then the solution is to:
| cd submodule/path
git add /previouly/detected/untrack/content
git commit -a -m "untracked"
|
Refreshing submodules
To refresh get uptodate submodules all you have to do is to type:
| git submodule init
git submodule update
git submodule foreach git pull origin master
|
Then you will wan’t to commit the changes which lead us to the following function
| # get latest submodules
function submodules_latest {
# init update and retrieve last head of each submodule
git submodule init
git submodule update
git submodule foreach git pull origin master
# Commit the submodule changes
git add .
git commit -a -m "Update submodules to the latest version"
git push origin master
}
|
Delete a submodule
Because, one day, you will wan’t to do it. Here are the steps to perform in ordrer to remove a submodule.
- Delete the relevant section from the .gitmodules file.
- Stage the .gitmodules changes git add .gitmodules
- Delete the relevant section from .git/config.
- Run git rm –cached path_to_submodule (no trailing slash).
- Delete the entry in .git/modules. Run rm -rf .git/modules/submodule_name
- Commit.
- Delete the now untracked submodule files. Run rm -rf path_to_submodule