How to Make .Gitignore Configurable Based on Environment Variables

Is it possible to make .gitignore configurable based on environment variables?

Currently the answer is no Yes, but not using an environment variable.

My use case is simple; I'd like to avoid accidentally checking in changes that I've made to a specific file so I can run my code locally.

Let's say I add my super secret password to the src/assets/secrets.xml file so that I can run my code locally, but I never want my password to leak to github so it can be found with tools like this.

Originally I thought having the ability to export GITIGNORE=path/to/that/file would be helpful in this circumstance.

But since that's not an option, here's how to accomplish the same goal.

git update-index --assume-unchanged src/assets/secrets.xml

To undo this effect:

git update-index --no-assume-unchanged src/assets/secrets.xml

After re-reading the OP's question a couple of times, I'm not sure if this will do what he's asking.

Using gitignore to separate development and production environments

Put the application with a the required profile under configuration management (git) and ignore any (local) overriding file.

For example, put a file named .env.dist under version control, while the file .env is in the .gitignore file of the same project (in that same path):

# dot env
/.env

Make your utility/bot load any .env.dist file by default and .env file overriding that .env.dist file. This allows you to document, plan and define required environment variables while allowing a user to keep a local copy with all the production credentials (if needed).

Then give your bot another parameter to load a different name environment (dot env) file taking the lead. This allows you to run the bot with any different configuration.

If you follow the syntax of environment files as used by the Docker CLI utility, you are most likely pretty inter-operable and can reach far by so w/o giving up much of your freedoms.

So take this as a suggestion.

Another one: If you would like to use diff-utilities to quickly compare between environment files, one tip I can provide is that if you create sections (as otherwise you should order the environment parameter (variable) names by name), give each section a header with (if not on top of the file) an empty line, a singe # comment, another comment with the section name # name of section and another single # line. This gives text-base diff tools enough food to keep sections apart of each other (and apart from other single-line comments).

#
# DISCORD API
#
DISCORD_ID
DISCORD_KEY

#
# MYSQL DATABASE
#
MYSQL_HOST
MYSQL_PASS
MYSQL_PORT
MYSQL_USER

(exemplary .env.dist file hinting required parameter while not providing any secrets)

#
# DISCORD API
#
DISCORD_ID=42
DISCORD_KEY=aefdcd8d71d200efaefdcd8d71d200ef

#
# MYSQL DATABASE
#
MYSQL_HOST=example.com
MYSQL_PASS=root
MYSQL_PORT=34732
MYSQL_USER=root

(exemplary .env file containing secrets and excluded (do not add!) via .gitinore in the git project directly).

Add more "dot env" files into .git/info/exclude and/or if you adopt this pattern to your whole development system into your global .gitignore. Read the description in the Git gignore Documentation how the (multilevel) gitignore is used and when it does not ignore any of the files even if specified.

Can I use macros/variables in a `.gitignore` script?

Well, I'll just jump to the end of the semantics debate in the comments and leave it at this:

.gitignore is not a script, it's a list of patterns. As you would then expect, it has no support for variables.

If you really need this ability, I would take a cue from the likes of sass or less: Write your own file of "ignore rules with extended syntax" and write a script to boil that down into a proper .gitignore file.

But if you want my two cents, this looks like another case that would be resolved by moving some stuff outside your work tree, so that the work tree can just be a work tree.

Why do people put the .env into gitignore?

Your .env file contains very sensitive information (your app key at the very least). You do not want this in version control where everybody can see this information and possibly use it to attack your site.

Think about database information which might be stored in there or email keys or passwords. Furthermore it is likely that the information which you use in your .env file also needs to change between environments so you will need to change values anyways.

What should you instead do?

Make a file .env.example in this file you place all the keys of your .env.

ex.

APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

Here you can see a file in which all the necessary information for somebody that wants to use your code is available but none of the sensitive information. Then somebody can copy this .env.example to .env and change the values.

What does a gitignore global config do exactly?

The core.excludesfile works like a .gitignore file, but it has a different purpose. A .gitignore file is project specific and it's designed to contain various things that the project wants to ignore, often because they're build products. For example, a project written in C will probably want to ignore the built binary or shared library, plus any files matching *.o or *.obj. These are things that every user of your project will want to ignore.

The core.excludesfile is designed for patterns you personally would like to ignore. For example, if you use Vim, you'll probably want to ignore swap files so that you don't accidentally check them in. Since people use many different editors, it doesn't make sense to ignore every different type of editor file in every project, so this is an opportunity to ignore things like editor backup files, tags files, and similar stuff.

There's also a third set of configuration, which is in .git/info/exclude. Since it's in the .git directory, it's specific to the project, but it's not shared. It's for cases when you need to modify the project's include patterns for your local system, but in a way that isn't relevant to others. For example, I have a project where I have a dotfile to help my editor find the real root of the project, and this file is specific to my configuration.

So to answer your question, you should still write .gitignore files for your projects if they have build products or other project-specific data to ignore. There is no way to dynamically or automatically configure the patterns, but usually you should not need to do this.

Note that in your case, you need to write the pattern as ~/.gitignore. Git does not expand environment variables in the config file, but usually ~, which represents the home directory, will match the value of the USERPROFILE environment variable.

How do I configure git to ignore some files locally?

From the relevant Git documentation:

Patterns which are specific to a particular repository but which do not need to be shared with other related repositories (e.g., auxiliary files that live inside the repository but are specific to one user's workflow) should go into the $GIT_DIR/info/exclude file.

The .git/info/exclude file has the same format as any .gitignore file. Another option is to set core.excludesFile to the name of a file containing global patterns.

Note, if you already have unstaged changes you must run the following after editing your ignore-patterns:

git update-index --assume-unchanged <file-list>

Note on $GIT_DIR: This is a notation used all over the git manual simply to indicate the path to the git repository. If the environment variable is set, then it will override the location of whichever repo you're in, which probably isn't what you want.


Edit: Another way is to use:

git update-index --skip-worktree <file-list>

Reverse it by:

git update-index --no-skip-worktree <file-list>

gitignore vs environment variables Ruby on Rails

There's no strongly compelling reason to prefer environment variables over files, but I'm not sure I'd feel comfortable relying on .gitignore and keeping the files in the source tree. If you opt for files, you might want to consider moving them outside the source tree to avoid any mistakes.

If you've committed the files at any point in the past (particularly to a public site like GitHub), then adding them to .gitignore later isn't going to remove the copies of previous versions that were committed; they'll still be in the repository, and someone could browse back to a version where they weren't ignored.

Additionally, depending on how you run your app, having them in the same directory as the app may make you more vulnerable to web-based security holes. If you keep them outside the app tree, you may gain some limited protection from exploits that can read arbitrary data from the app tree. I don't know that this is all that much of a concern (an exploit that can read within the app tree can probably read outside it too), but it wouldn't hurt to keep them in another directory.

I tend to prefer environment variables because it makes deploying to Heroku easier, so I use them in development too. I'd probably use a file for anything more than simple login/password pairs (RSA keys, etc), and store it in my home directory or somewhere under /var/lib or /etc or /usr/local or something.

How do I make Git ignore file mode (chmod) changes?

Try:

git config core.fileMode false

From git-config(1):

core.fileMode
Tells Git if the executable bit of files in the working tree
is to be honored.

Some filesystems lose the executable bit when a file that is
marked as executable is checked out, or checks out a
non-executable file with executable bit on. git-clone(1)
or git-init(1) probe the filesystem to see if it handles the
executable bit correctly and this variable is automatically
set as necessary.

A repository, however, may be on a filesystem that handles
the filemode correctly, and this variable is set to true when
created, but later may be made accessible from another
environment that loses the filemode (e.g. exporting ext4
via CIFS mount, visiting a Cygwin created repository with Git
for Windows or Eclipse). In such a case it may be necessary
to set this variable to false. See git-update-index(1).

The default is true (when core.filemode is not specified
in the config file).

The -c flag can be used to set this option for one-off commands:

git -c core.fileMode=false diff

Typing the -c core.fileMode=false can be bothersome and so you can set this flag for all git repos or just for one git repo:

# this will set your the flag for your user for all git repos (modifies `$HOME/.gitconfig`)
# WARNING: this will be override by local config, fileMode value is automatically selected with latest version of git.
# This mean that if git detect your current filesystem is compatible it will set local core.fileMode to true when you clone or init a repository.
# Tool like cygwin emulation will be detected as compatible and so your local setting WILL BE SET to true no matter what you set in global setting.
git config --global core.fileMode false

# this will set the flag for one git repo (modifies `$current_git_repo/.git/config`)
git config core.fileMode false

Additionally, git clone and git init explicitly set core.fileMode to true in the repo config as discussed in Git global core.fileMode false overridden locally on clone

Warning

core.fileMode is not the best practice and should be used carefully. This setting only covers the executable bit of mode and never the read/write bits. In many cases you think you need this setting because you did something like chmod -R 777, making all your files executable. But in most projects most files don't need and should not be executable for security reasons.

The proper way to solve this kind of situation is to handle folder and file permission separately, with something like:

find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \; # Make files read/write

If you do that, you'll never need to use core.fileMode, except in very rare environment.



Related Topics



Leave a reply



Submit