20

I know many people store their .vimrc on GitHub to make it easier to get right to work on new machines, and that makes complete sense to me. Including plugins, however, is problematic, because the plugins I use are already git repositories. How does one create a repo that will track both their .vimrc and any plugins that might be installed?

  • I feel like this might be too opinion-oriented; there's no objective "best" and there are a lot of good options, each with their own pros and cons. Also the bit specifically about nested repositories brings the question more into the "using git" category and less about vim. Perhaps if you focused instead on a specific problem you had with vim or vim plugins while trying to store your configuration on github? – Josh Feb 6 '15 at 18:20
  • 3
    I can edit it to take out the best if you like; my intention was to ask more of a "how do I do this?" question, while acknowledging that the way I was thinking about going about the problem might not be ideal. – Tom Feb 6 '15 at 18:21
  • That may help, but that may just make it a "list of things" question (there are, again, lots of different ways to do this effectively). There's currently a topic on meta about such questions if you'd like to contribute to the discussion about how we should treat this sort of question. – Josh Feb 6 '15 at 18:24
  • 1
    Edited. I hope I've made it more clear that I'm asking "how do I do this?" – Tom Feb 6 '15 at 18:29
  • 1
    Just use a plugin manager like neobundle. – Philip Mar 9 '15 at 15:12
18

How to deal with repositories-within-repositories has been an ongoing question with git. Git's submodules are one way of addressing the situation, at the expense of adding a little more complexity to keep track of. The git site has an introduction to submodules.

The basic idea is to keep a reference to another git repository associated with a path on your repository. These references are stored in a file .gitmodules in the root of your repository (which is managed by git, so leave it alone). Some of the complexity comes in to play when cloning a repo which has submodules: you must explicitly git submodule init to create the .gitmodules file, and then git submodule update to clone the submodules.


Here's a walkthrough of how I'll add a new vim plugin to my dotfiles repository (I have ~/.vim/ aliased to this repo's .vim/) using a submodule:

$ cd dotfiles/
$ git submodule add https://github.com/elixir-lang/vim-elixir.git .vim/bundle/vim-elixir

After the submodule add, a git status would show that you've modified (or created) the .gitmodules file, with something like this:

[submodule ".vim/bundle/vim-elixir"]
    path = .vim/bundle/vim-elixir
    url = https://github.com/elixir-lang/vim-elixir.git

It should also show .vim/bundle/vim-elixir as a new file. Git treats that path specially now: it's a normal directory on your file system (so vim loads it up normally), but git diff will treat it as a specific commit from its repository. When looking at diffs or logs for that path (e.g. git log -1 -u .vim/bundle/vim-elixir), git will show it as a one-line string like this:

Subproject commit 2d59d1d52a9bcf9342d42fa7d6b59e6a1aaa7b9e

Updating to the latest version of the plugin corresponds to going into the submodule's repository and checking out a new commit, and then committing that to your repository:

$ cd .vim/bundle/vim-elixir
$ git remote -v            # note: the submodule repo's origin, not my repo's
origin  https://github.com/elixir-lang/vim-elixir.git (fetch)
origin  https://github.com/elixir-lang/vim-elixir.git (push)

$ git pull
# ...

$ cd -     # back to my repository's root
$ git status
# ...
    modified:   .vim/bundle/vim-elixir (new commits)

$ git diff .vim/bundle/vim-elixir
# ...
-Subproject commit 2d59d1d52a9bcf9342d42fa7d6b59e6a1aaa7b9e
+Subproject commit d59784e7afbd0d55c501e40c43b57cbe6f6e04c2

$ git commit -m "update vim-elixir" .vim/bundle/vim-elixir
  • Thanks, that looks like just the sort of thing I was looking for! – Tom Feb 6 '15 at 19:05
  • Ah, I didn't notice your answer had been posted, since I was editing mine for some time. – muru Feb 6 '15 at 19:29
22

You don't need to store plugins in your VCS; you can also use a Vim package manager. Since yesterday, I use vim-plug:

You can define plugins in your vimrc like so:

call plug#begin('~/.vim/plugged')

Plug 'embear/vim-localvimrc'
Plug 'kchmck/vim-coffee-script'
" ... etc

call plug#end()

Then restart Vim, and then install plugins with:

:PlugInstall

Or, you can add this snippet from the FAQ to your vimrc file before the plug#begin() call:

if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall
endif

This will put the plugins in ~/.vim/plugged. You do not need to keep this file in your VCS. If you want to use this vimrc on another machine, just call :PlugInstall on that machine.

to remove a plugin, remove it from the vimrc file and run:

:PlugClean

Note that vim-plug doesn't support installing scripts from the Vim scripts website, but those scripts are mirrored on GitHub, so there's no need to do so.

There are also some additional advantages to this such as easier updating of plugin, and on-demand loading for better performance. You're also not running the risk of violating the license terms of the plugins you're distributing with your vimrc files.

See also:

5

I store my vimrc in github and the plugins as submodules of my repository.

In the readme.md file I put a one liner that pulls the repository then runs the setup script, this way I can copy one line into an editor and it sets up everything. It does a bit more than just vim (but not much).

https://github.com/Loki-Astari/UnixConfig

To use it:

cd
git clone git@github.com:Loki-Astari/UnixConfig.git ~/.config
cd .config
git submodule init
git submodule update
chmod +x init
./init
cd

PS. Willing to take any advice (as I did this ages ago and have not touched it since).

Note: My favorite part is that it sets up git as well and sets it up to use vim as the diff tool for git. Vimdiff is the the best diff tool.

5

If you would like to stick with Pathogen, one way could be to use Git submodules. When you add a submodule, git recognizes it as from another repository and leaves its contents alone (unless it has been changed, in which case, it will show up as having untracked content when you do git status). If you all your Github-based plugins are in bundle/, then adding them as submodules is a fairly simple task with a good shell:

for f in bundle/*/ 
do 
    git submodule add $(awk '/url =/{print $3}' "$f/.git/config") "$f"
done

You can have a look at how submodules show up at my vimrc repo.


If you add a file to a submodule, or make some changes that don't affect the repository, git status will still complain about the submodule having uncommitted changes or untracked files. You can make git ignore such changes by adding ignore = dirty to the submodule configuration in the .gitmodules file. For example:

[submodule "bundle/LaTeX-Box"]
    path = bundle/syntastic
    url = https://github.com/scrooloose/syntastic.git
    ignore = dirty

One benefit of submodules is that revision of the submodule is added to the git repository, so that a git init automatically takes care of checking out up that particular revision. You can throw that away and tell git to ignore submodules once you have added them by adding ignore = all to their configuration in the .gitmodules file. For example:

[submodule "bundle/LaTeX-Box"]
    path = bundle/LaTeX-Box
    url = https://github.com/LaTeX-Box-Team/LaTeX-Box.git
    ignore = all

Lastly, one command to update them all!

git submodule foreach git pull

Word of caution: I am new to submodules. I am not really sure how they behave.

  • vim-pandemic is another way to enhance Pathogen without needing to use submodules. Pandemic handles the remote repositories leaving Pathogen to handle the runtimepath. This does mean one needs two tools, but for disparate tasks which "should" be handled separately. – jalanb Feb 9 '15 at 10:43
  • Can anyone comment on why tpope in the pathogen readme might say why submodules are not the way to go? I don't know submodules either (and my solution works great for me without even a plugin manager) but I'm guessing the anti-submodule crowd has something interesting to say. – dash-tom-bang Feb 22 '16 at 18:11
  • 1
    @dash-tom-bang I don't read that bit as him saying that you shouldn't use submodules. I think he's just saying it's not his preferred method. – Rich Mar 13 '18 at 15:27
  • 1
    TBH after a couple of years of using them, I got annoyed with submodules. I would now recommend against using them. I use vim-plug now and it's only made my life easier. – muru Mar 13 '18 at 15:40
4

You can just add this line to your .gitignore to ignore all your plugins and not commit them:

vim/bundle

Also, you said that it's problematic that it would include the plugin code because they're already github repos. I guess you mean that you don't want to duplicate the code, but I've heard it said that you should go ahead and duplicate code that's a dependency so that you can always go back to a particular point in your code and know that it will work. Here are some articles by James Shore that talk about that: http://www.letscodejavascript.com/v3/blog/2014/12/the_reliable_build, http://www.letscodejavascript.com/v3/blog/2014/03/the_npm_debacle. He's talking about programming code and npm (as opposed to vim), but I think the argument still applies, you want a reliable environment to code or write in.

  • 1
    "You can just add this line to your .vimrc..." did you mean .gitignore? – Josh Feb 6 '15 at 19:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.