'Ignore other .gitignore files than the one in root
My Actual Question
I would like that only the .gitignore file in the root of my directory structure ignore files, i.e, the .gitignore files in subdirectories shouldn't ignore files.
To be clear
I don't want to gitignore other .gitignore files. I want them to be commited to git but I don't want them to gitignore other files.
Specific use-case
Let's say I want to commit a boilerplate project structure to git. Let's say the project structure looks like this:
project-root/
│
├── boilerplate/
│ ├──directory/
│ ├──some-other-directory/
│ ├──.env
└── └──.gitignore // Has a line ".env" which will ignore the .env file in this directory
│
├── boilerplate2/
│ ├──directory/
│ ├──some-other-directory/
│ ├──.env
└── └──.gitignore
│
└── .gitignore // The .gitignore in root
Now the .gitignore file in boilerplate directory will gitignore .env which I don't want. How can I stop nested .gitignore files from taking action?
What I tried?
I tried the negation (!) operator in the main .gitignore file. For the sample structure above, it's equivalent to !boilerplate/.env. The .gitignore in root simply doesn't have any power over the .gitignore file in the specified directory. It doesn't override it. Why does it work like that? Is there a workaround?
Edit:
VonC suggests to automate that using scripts, but that's not the question. The question is, how to do that using only .gitignore, if it is possible at all.
Solution 1:[1]
Now the .gitignore file in boilerplate directory will gitignore .env which I don't want.
It will not.
If boilerplate/.env is already added (git add --force) and committed, any change to that particular .env file would still be detected, not ignored.
The OP adds:
But when I do git status, git ignores boilerplate/.env due to boilerplate/.gitignore (which isn't commited either)
Then, yes, it will ignore all .env, unless they are themselves versions.
The
.gitignorein root simply doesn't have any power over the.gitignorefile in the specified directory.
It doesn't override it.
That follows the precedence rules for a .gitignore:
Patterns read from a
.gitignorefile in the same directory as the path, or in any parent directory (up to the top-level of the working tree), with patterns in the higher level files being overridden by those in lower level files down to the directory containing the file.
In your case, I would:
- keep the
.envrule - version only
.env.tpltemplate files with default initial value - add a
.gitattributesfile with a smudge content filter driver script declaration for*.tpl
That smudge script (for instance, 'script_tpl', which can be versioned as well) would be a bash script (which does work even on Windows, since Git for Windows comes with bash.exe):
#!/bin/bash
file="${f%.tpl}" # ex: .env.tpl => .env
if [[ ! "${file}" ]]; then cp "${f}" "${file}"; fi
I would add an senv script to be executed by any collaborator using a local cloned of the repository, in order to register automatically the content filter driver. It would include:
#!/bin/bash
DIR="$( cd "$( dirname "$(readlink -f "${BASH_SOURCE[0]}")" )" && pwd )"
# assuming the smudge script is at the root of the repository
which script_tpl || export PATH=${PATH}:${DIR}
git config --global filter.tpl.smudge 'script_tpl'
That way, any time you switch branch, the smudge script with check if .env does exist and, if not, will create one (which will be ignored by all the various .gitignore files)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
