I'd .gitignore those files.
There's the idea that configuration is not part of the code – it describes the environment that a software is being deployed in. This view is promoted e.g. by The Twelve-Factor App, a guide to building SaaS by Heroku.
Because the deployment environments differ, it makes no sense to check in environment-specific configuration to your software's version control. Instead, the deployment environment should provide the necessary configuration itself, e.g. via environment variables. Using .env
files is just a convenient way for managing environment variables with some frameworks.
But some things do not differ between deployment environments. Those things are code and should be checked in. In particular, I would expect a software to run in a sane default configuration if there are no environment variables, with the only required parameters being connections to other services (e.g. a database connection string).
Story time: I worked at a place where we developed some enterprise software with various services. To my delight, the tests were easy to run. And I ran them often. Until one day, a senior engineer came to my desk and asked me to stop using his database for my tests! What had happened? The engineer had checked in his configuration file and added a connection string to a test database he had running somewhere. I didn't know that, so I was overwriting his data all the time. Not good.
Of course I immediately started my own database instance and modified the configuration file, but for the rest of my time there I had to remember to never commit my modifications to that file since it would overwrite my team members' configuration…
From the 12-factor perspective, the problem was that a configuration was checked in that was specific to one deployment environment, but was not provided by the deployment environment. If there hadn't been a default configuration file, the software would have loudly complained that it didn't have a database connection so I would have known to set one up.
Even better would have been if the test environment had been completely automated so that I could spin up a test deployment and it would configure itself. Back then, we couldn't use Docker. But now, it's super easy to define a reproducible deployment environment. I often write docker-compose files that spin up the necessary containers and connect them as appropriate. In the definition of those services, I can also define environment variables that are injected into the containers. Since these env vars only refer to services within this reproducible test environment, that is safe to do. But the important point is that the environment (as defined in the docker-compose file) provides its configuration to the software.
You don't have to use docker-compose or similar technologies if they don't make sense. You don't have to build a 12-factor app. But I would invite you to re-consider the role of this .env file:
- What is in this environment that is boilerplate? Why isn't it a default of your software?
- Why is it necessary to provide configuration in order to get a test or development environment? Why can't this be scripted or automated in any way?
Additionally, consider security implications. It is fine to disagree with this answer and to commit configuration that is specific to a deployment environment. However, Git is blockchain-like: an append-only data structure that prevents later modifications. The most you can do is to record an alternate history and then forget about the original history. So if you commit a secret once, it remains in the Git repository forever, unless and until you learn about history rewriting with git filter-branch
and put up with the wonderful world of merge conflicts that are likely to result. A world of headaches awaits you. It is much better to never commit secrets in the first place. This also reduces the impact of accidental leaks, like accidentally putting a .git
folder under the webroot of a web server (been there, done that). For managing secrets in a team, use a password manager.