2

I want to create a git repo of my bash settings and plugins and whatnot. I have ignored everything (line 0) and then manually added the files/folders that I want in the repo. (I have to do it this way because the repo is in my ~ folder.) I want to ignore all colour profiles in the .vim/colors/ directory, but I do want to include the one file that I am using (apprentice.vim).

The .vim/colors/* line doesn't seem to work - it doesn't ignore any of the files at all. Using !!.vim/colors/* doesn't work either. How am I supposed to make it override all previous rules and ignore the colors folder, then still allow the apprentice.vim file to be ignored?

/*

*.swp

!.gitignore

!.bashrc
!.bash_profile

!.vimrc
!.vim
.vim/colors/* # Don't include all of the other color schemes
!.vim/colors/apprentice.vim
Dylanthepiguy
  • 1,621
  • 18
  • 47
  • Is that a literal copy of the `.gitignore` file, with a comment as part of a line? If so, that's the problem: comments must be on their own separate lines. – torek May 29 '16 at 07:29
  • @torek the actual problem is the '`colors/`' folder is ignored. See [my answer below](http://stackoverflow.com/a/37507408/6309) – VonC May 29 '16 at 07:42
  • @VonC: ah, yes, this one always tends to trip me up. I try never to allow entire directories to match in `.gitignore` files. – torek May 29 '16 at 07:44

2 Answers2

8

The issue was the # comment on the same line as .vim/colors/*, but here is an alternative.

The main rule for gitignore is:

It is not possible to re-include a file if a parent directory of that file is excluded.

That means:
(assuming the elements are not already versioned, in which case you need to git rm --cached them first):

  • you need to ignore all the files recursively: that is '**'
  • exclude all the folders recursively: those are '**/'
  • exclude the file you want (which will work because its parent folder is not ignored as well)

Result:

/**
!/**/
!exclude what you want to *not* be ignored
# for instance
.vim/colors/* # Don't include all of the other color schemes
!.vim/colors/apprentice.vim

Check what is and is not ignored with git check-ignore -v (the -v is important):

git check-ignore -v -- afile

It is easier than un-ignoring a sub-folder manually, especially when the sub-folder content to un-ignore is several level deep: to exclude a file in a/b/c, you need first to un-ignore !/a, then !/a/b, then !/a/b/c)


Illustration/test:

C:\Users\vonc\prog\git\tests>git init i
Initialized empty Git repository in C:/Users/vonc/prog/git/tests/i/.git/

C:\Users\vonc\prog\git\tests>cd i

C:\Users\vonc\prog\git\tests\i>mkdir .vim\colors

C:\Users\vonc\prog\git\tests\i>touch .vim\colors\apprentice.vim

C:\Users\vonc\prog\git\tests\i>git st
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .vim/

nothing added to commit but untracked files present (use "git add" to track)

Simple .gitignore with /* rule:

C:\Users\vonc\prog\git\tests\i>sbt .gitignore
/*

C:\Users\vonc\prog\git\tests\i>git st
On branch master

Initial commit

nothing to commit (create/copy files and use "git add" to track)

Lets add !.gitignore.
.gitignore can now be tracked.

C:\Users\vonc\prog\git\tests\i>git st
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

nothing added to commit but untracked files present (use "git add" to track)

But if I add:

.vim/colors/*
!.vim/colors/apprentice.vim

.vim all content is still ignored:

C:\Users\vonc\prog\git\tests\i>git st
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

nothing added to commit but untracked files present (use "git add" to track)

Let's check why with git check-ignore:

C:\Users\vonc\prog\git\tests\i>git check-ignore -v -- .vim\colors\apprentice.vim
.gitignore:1:/* ".vim\\colors\\apprentice.vim"

Adding !.vim works, because it un-ignore the folder, allowing the other rules within that folder to apply.

Still, this is simpler:

/**
!/**/
!.gitignore
.vim/colors/*
!.vim/colors/apprentice.vim
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I marked this as correct, although all my other root folders (documents, downloads, etc) show as unstaged by git when I use ` /** \n !/**/` (don't take the "\n" literally). I have decided not to use a git repo for this purpose though, because when I am in any path within my home directory git status will show the status of the repository (when there isn't any other git repo there) , which is rather annoying. – Dylanthepiguy May 30 '16 at 07:28
  • @Dylanthepiguy unstaged? So you could `git add` them? Those folders should not show up, unless you have done a git init in the wrong place (as in C:\). Do you have a `.git` folder somewhere else? – VonC May 30 '16 at 07:29
  • Oh I've already `rm -rf `'ed the .git folder. I didn't have any other gits lying around since gave the "fatal: not a git repository" error (something like that). I didn't try adding them, but would any folder ever show up if it was ignored? – Dylanthepiguy May 30 '16 at 08:06
  • @Dylanthepiguy in a local git repo, you should now have any windows folder Downloads, documents, ...) showing up. What is your current working path when you do a `git status` and you see those folders? – VonC May 30 '16 at 08:07
  • I did a git status somewhere in ~/Dropbox/Programming/ but as I said, I already did a `rm -rf` on the ~/.git folder so I can't really reproduce it now – Dylanthepiguy May 30 '16 at 08:35
  • Nevermind, I re-inited the repo for testing and the Dropbox, Downloads, etc folder doesn't show up in git status. However the `.vim` folder doesn't show up in status as well – Dylanthepiguy May 30 '16 at 19:35
  • @Dylanthepiguy Did you try with the `/** !/**/` approach that I mention in my answer at the end? – VonC May 30 '16 at 19:51
2

Your rules seem to be fine. Except *.swp would be covered by /* and the comment not being on its own line.

As you can see all other .vim/colors are ignored. enter image description here

If your files have already been staged, you may need to unstage them and remove them from the repository, then readd them.

git rm --cached ./.vim/colors/*
git add ./.vim/colors/
git commit -m"Unstaged .vim/colors"

Final .gitignore to use

/*
!.gitignore

!.bashrc
!.bash_profile

!.vimrc
!.vim
.vim/colors/*
!.vim/colors/apprentice.vim
Will B.
  • 17,883
  • 4
  • 67
  • 69
  • That will not work because the `colors/` folder itself is ignored. Any rule within the `colors/` folder will be ignored as well: once a folder is ignored, git does not look into it at all. – VonC May 29 '16 at 07:40
  • It does with `!.vim/colors/apprentice.vim` which is why `/*` `!.gitignore` works, as well as the others. – Will B. May 29 '16 at 07:44
  • @VonC additionally look at the folder structure of the image I posted, which is the output from `.git` processing the ignore file - proving it works. However with the `comment` on the same line, will cause that line to be ignored by .git when processing the .gitignore file. – Will B. May 29 '16 at 07:48
  • No, it will not work, I just tested it (git 2.8.3). `git check-ignore -v -- .vim/colors/apprentice.vim` correctly says it is ignore because of the `/*` rule. `/* !.gitignore` works because `/` itself (the folder) is not ignored. Only its content. Within the *same* folder, you can un-ignore. Not within nested sub-folders. – VonC May 29 '16 at 07:50
  • I tested with git `1.9.4` and `2.8.3` which applies to the same rules according to the article you linked. Again, my screenshot proves it is working. Rebuilt it using the same rules, and everything results the same as the screenshot I took. Remove the `# Don't include all of the other color schemes` from your gitignore and run your `git check-ignore -v` again. – Will B. May 29 '16 at 07:59
  • I agree, I missed the `!.vim` rule, which un-ignore the `.vim` folder. I still find un-ignoring all sub-folder easier (you don't have to un-ignore all sub-folders one by one manually) – VonC May 29 '16 at 08:03
  • Very much so agreed on that one. Makes managing it much easier as you can clarify what is ignored rather than having to verify what is not. However the user's case being in the user profile directory may make that not-possible. – Will B. May 29 '16 at 08:07