DEV Community

Don't commit that file!

Chris DeLuca on November 29, 2018

I wrote a small git pre-commit hook to prevent committing certain files. There are more words to this, but if you're impatient, you can skip right ...
Collapse
 
oleksiyrudenko profile image
Oleksiy Rudenko

I've noticed one effect when adding a file to .gitignore. It wasn't removed from repo.

Steps To Reproduce:

  1. Create and complete a file
  2. git add <file> && git commit -m "Initialize <file>"
  3. List the file among exclusion rules in .gitignore

Expected effect:
The file is committed while any further changes thereto get ignored.

There might be problems. Like what happens when we switch branches? How to ensure that if we DO want to change the file for everybody, how to ensure this?

I didn't test the above. Just for your consideration.

Collapse
 
dovidweisz profile image
dovidweisz • Edited

Adding a file to .gitignore doesn't remove it from git. It just ignores it in the "working tree", and when doing bulk adds (IE: git add . or git commit -a).

You still can stage such changes with git add -f.

Collapse
 
bronzehedwick profile image
Chris DeLuca

Correct.

If you need to remove the file from the git cache but not from the file system (aka, if you had a file checked in and then added it to .gitignore), you can run:

git rm --cached path/to/file

Thread Thread
 
dovidweisz profile image
dovidweisz

git rm --cached path/to/file

Cool I learned something new today

But I'm a little confused about your use case. It seems to me that adding the file to .gitignore would do the trick.

Thread Thread
 
bronzehedwick profile image
Chris DeLuca

The use case in my post is admittedly pretty specific, but we don't want to add the config files to .gitignore because the files are needed for the codebase to run properly. These config files also happen to have debugging options in them, so you have to modify the git working tree to enable them.

Collapse
 
oleksiyrudenko profile image
Oleksiy Rudenko

You are perfectly correct. And that's the point. One can "freeze" the file at the state it's been at the moment of adding to .gitignore.

I was addressing the following fragment from TS:

we have some configuration files tracked in git that we modify locally to enable debugging options. We don't want to ignore these files and have to manage them in a different system outside of git, but we also don't want the debugging options checked in.

Collapse
 
joshcheek profile image
Josh Cheek

I think this is fun, but that the correct solution is to stage files one at a time, after confirming they contain what you expect. This allows you to be incredibly hectic in your development, because you can trust yourself to reel it all back in at commit time. It also means you won't accidentally commit secrets (eg keys) or random files that accidentally wound up in the directory. It also means your commits will probably be much more coherent, b/c you'll be much more aware of what's in them, and you can break them into sensible chunks (eg git add -p)

Collapse
 
dovidweisz profile image
dovidweisz

Hmm, like to commit often, and use git commit -av. The verbose option gives me a diff, which I use to make my pre-flight checks.

Collapse
 
joshcheek profile image
Josh Cheek

Nice, I didn't know about commit -v I still have to do it one file at a time, though. If I don't think about what's in the file before looking at the diff, I wind up glossing over it and not being in tune with my commits.

Collapse
 
grmnsort profile image
German Rodriguez Ortiz • Edited

Hi,

At work, we had the same problem, but we ended trying a different approach.
What we do is having a .dist version of every file that we want to keep tracked "as is" but don´t want to track changes that people do over them, and in the .gitgnore we simply ignore the "non .dist files". So in the end we have a tracked file structure like this:

├── app
│   ├── config
│   │   ├── some-general-config.yml
│   |   ├── local-parameters.yml.dist
│   |   ├── variable-config.yml.dist
|-- .gitignore

and in the .gitignore we just add:

/app/config/local-parameters.yml
/app/config/variable-config.yml

That way everyone (including our testing and production environments) get a copy of the config files that provide the exact info to each app instance that we have. Right now when you clone an instance, you would have to manually create the "real" copies of the config files and edit them, but we´re making a script that we intend to run on our composer install phase that will add a stage that does this automatically.

Collapse
 
bronzehedwick profile image
Chris DeLuca

Hey Germán, that's a nice solution. Unfortunately we can't tell our app to recognize a different config file, but you gave me an alternate idea. Perhaps there's a path in YAML where we have the regular config file checked in, then have a local config file that overrides any values set in the general that's in .gitignore. The YAML in the general file would be something like:

source: my-local-config.yml
Collapse
 
mhzprayer profile image
Matt Hernandez

For some reason this made me think about the Google movie where they made an app to prevent yourself from sending drunk texts..be careful before you send that file out ON THE LINE!

Collapse
 
bronzehedwick profile image
Chris DeLuca

Oh wow, I completely forgot about that. Wasn't that a Gmail Labs thing at one point? Mail Goggles? I guess I have to cop to re-inventing a weird old gmail filter haha.