53

I'd like to create one single git repo in my Linux $HOME directory. In this repo - obviously - I could add everything under version control, but this wouldn't make any sense. I'd like to only add the files and folders that are relevant to me, like .vimrc, .vim, .bashrc, etc. (probably only hidden files and folders, but maybe not)

I know I could leverage .gitignore to try and achieve such behavior but that would be painful and virtually un-maintainable. Instead, what I'd want to know is if there'd be any way to manually declare files and folders that I would want to manage, and only that.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Aurelien Navarre
  • 655
  • 1
  • 6
  • 8
  • 3
    You mean something like [dotfiles](http://blog.smalleycreative.com/tutorials/using-git-and-github-to-manage-your-dotfiles/)? – Roman Jan 21 '14 at 19:14
  • possible duplicate of [Adding your .vim ~/.vimrc to github (aka dot files)](http://stackoverflow.com/questions/18197705/adding-your-vim-vimrc-to-github-aka-dot-files) – Roman Jan 21 '14 at 19:16

5 Answers5

53

.gitignore

# Ignore everything
*

# But not these files...
!*.vimrc
!*.vim
!*.bashrc
!.gitignore

# etc...

My home directory is also on GitHub.

Niklas
  • 23,674
  • 33
  • 131
  • 170
  • 2
    Would the new `.git` dir. created by `git init` conflict with any of the existing user-specific config. typically found in the home dir.? – Jared Beck Sep 28 '14 at 19:58
  • 6
    I know it's what the op asked, but I personally don't like this approach. You will never be automatically warned if something new appears in your home directory. Ideally you just decide once for everything in there whether to ignore it or keep it. I'm trying right now with a clean debian install, but admittedly there is already quite some cruft in there. A good sample .gitignore file for /home would be a great resource cause anything new should be new software you install, in which case I at least want to see it appear and decide whether I want it's configuration in my vcs. –  Feb 05 '15 at 19:21
  • The advantage being, if I reinstall or migrate etc I can add the old repo as a remote, and then get all my configs for all my software and merge in what I want. Not just .bashrc and a few other things. –  Feb 05 '15 at 19:23
  • 1
    This is great but not if you have other Git modules in your home directory. – Alex Harvey Jul 16 '18 at 00:14
  • @user1115652's point is a valid argument against this. However, we can use `git clean -nxd .[^.]*` to list all of the files ignored by the `.gitignore`. This is a fun substitute to list all _untracked_ files in our home directory since everything is ignored by the `*` rule, allowing us to find any potential extra configuration files we might want to track in the Git repo. We can also use `git check-ignore` to check if a file is ignored, but this behaves a bit differently than a `git clean` dry run. – Andrey Kaipov May 19 '20 at 18:36
  • To @JaredBeck's point, getting this repo onto another machine is not as straightforward and cloning into our home repo as it will almost always be non-empty and will already have files conflicting with our remote. The approach I've taken on new machines is the following: `git init; git remote add origin ...; git fetch origin master; git reset --hard origin/master`. The hard reset will remove any conflicting files. – Andrey Kaipov May 19 '20 at 18:40
  • Two days later, I think `git status --ignored` is actually the best way to check for anything new that pops up in our home directory. – Andrey Kaipov May 22 '20 at 02:18
  • This is really nice but I found it was better to use put these rules in `~/.git/info/exclude` instead of `~/.gitignore` so that search tools like `rg` do not ignore everything. – gondalez Oct 21 '20 at 06:34
38

I would setup an alias for use only with your home repo this way you can use the alias in place of git command and you always know the context you are working in

# .bashrc
alias home='git --work-tree=$HOME --git-dir=$HOME/.home'

Issuing the comand

$ home init

will create a repo in .home folder in your $HOME and irrelevant of current directory you can work with your home repo with the alias 'home' in place of 'git'

This alongside a .gitignore should be all you need.

# .gitignore
*
# keep track
!.bashrc
!.gitignore

NB. DO NOT KEEP .ssh/keys in repo as it presents file permission and security issues.

Pete
  • 614
  • 6
  • 4
  • 4
    This is a fantastic solution; thank you! My only change would be to not use `.gitignore` but instead use `$GIT_DIR/info/exclude` (so, `$HOME/.home/info/exclude`). I also prefer `$HOME/.home.git` or such, but this is superfluous mostly, with this alias at hand. – Nathan Schulte Apr 02 '17 at 22:04
  • 3
    Just curious, if I implemented this solution on machine A and cloned the repo on machine B, would git overwrite existing files in the home directory on B? – chmaynard Dec 08 '18 at 22:22
  • 1
    [A blog about this technique](https://www.atlassian.com/git/tutorials/dotfiles). A related [HN thread](https://news.ycombinator.com/item?id=11070797). – DharmaTurtle Dec 19 '21 at 18:36
  • This technique is incompatible with any git tools like Fork/GitKraken/Sourcetree. If you're happy with git CLI - great! If not... you'll either need to get over it or use a different technique. (Your tool _might_ support a custom `work-tree` and `git-dir` e.g. [Magit](https://emacs.stackexchange.com/questions/30602/use-nonstandard-git-directory-with-magit), but you'll need to research/do it yourself.) – DharmaTurtle Dec 19 '21 at 19:04
23

I would suggest not putting your $HOME directory under git version control. I did this, because I thought I was exceedingly clever and wanted my .dotfiles under version control. However, git is greedy and ravenous. I had to add tons of directories (or even *) to my $HOME/.gitignore. And do you have any git repositories elsewhere in your home directory? I did. But those git repositories will use your $HOME/.gitignore as your global .gitignore unless you set that elsewhere. So it's a real pain to try and add files in these sub-directory repositories.

Instead, put your important files in a separate directory. Say, ~/dotfiles. Now make that a git repository, and symlink all of your important .dotfiles to point at that new repository. Voila. Problem solved, albeit with some time invested in linking.

Mike Monkiewicz
  • 4,481
  • 1
  • 22
  • 19
  • 1
    Imagine forgetting you're in `~` and doing a `git clean -xdf`. (I do this on a regular basis in other repos to get it back to a clean state. Obviously the effects in `~` would be _disastrous_.) On a separate note, [chezmoi](https://www.chezmoi.io/) automates the symlinking if you set its config to `mode = "symlink"` – DharmaTurtle Dec 19 '21 at 17:03
11

I think you're looking for dotfiles.

Leonid Shevtsov
  • 14,024
  • 9
  • 51
  • 82
1

I think the best way is to set up a git repository in somewhere else (preferably in physically different disk) and adding your files in it.
You can creat empty git repo using doing
(at a safe file system, preferably different disk, like /home1)

sudo git init --bare mynewrepos.git
sudo chown -fR myself mynewrepos.git
sudo chgrp -fR myself mynewrepos.git

now, go to your home directory, and do

git clone /home1/mynewrepos.git   # now you are cloning from empty git repos.

then add your precious files to the git (git add, git commit, git push .. and all). I didn't try it for keeping my usual files under my home, but I use this method to manage my local project files (before uploading to official git repos.). But again, if you have many git managed files under your home, they might be affected by your .gitignorefiles under your home.

Chan Kim
  • 5,177
  • 12
  • 57
  • 112