41

I want to show off some of my work by uploading them to my GitHub account. However, there are some files that contain passwords, like database connections.

Is there a way of marking a file as uncommitable with Git so that it cannot appear on GitHub?

  • 1
    Tangential suggestion: This might not be applicable on every platform, since some are very married to configuration files, but you could consider following the 12factor approach of keeping these parameters in the environment: 12factor.net/config. That is, have the application code never assume the presence of a configuration file. (As opposed to a private startup script that sets these, but never leaves your local machine.) – millimoose Oct 26 '15 at 1:07
  • 1
    If you accidentally commit them, make sure you remove them from the fully git history (other questions will explain how) because even if you delete and ignore it the old committed version will remain in the history and be visible on Github. – curiousdannii Oct 26 '15 at 6:31
  • 3
    Note that all answers don't really answer your question. They do not make the file uncommitable, they simply configure git so that it ignores it by default. But if you accidentally insert that filename into a git command line you can end up commiting it even though it matches a pattern in .gitignore. AFAIK there is no 100% full-proof way of telling git to avoid commiting a specific file in all cases. Though this may be seen as a feature... allowing for explicit commands to override generic configurations. – Bakuriu Oct 26 '15 at 6:37
  • You could remove the hardcoded passwords and switch to an safer alternative. After that you can switch the Database passwords. The old passwords are still inside the commits but they're outdated once someone able than you is able to read them. I'm pretty sure that you cannot change a commit once it's already build upon. – BlueWizard Oct 26 '15 at 13:44
  • 3
    In addition to what @curiousdannii said, GitHub has an entire page discussing how to remove sensitive data you accidentally committed. Among other things, this page says to change any passwords and keys you accidentally published. help.github.com/articles/remove-sensitive-data – Kevin Oct 26 '15 at 20:34
67

Is there a way of marking a file as uncommitable with Git so that it cannot appear on GitHub?

First, there is no way to have some files and commits visible in your local Git repository but somehow not viewable in GitHub; if you have a file committed in Git it will show up in GitHub.

Second, there is no simple and practical way to ever mark an individual file itself as being “uncommitable.” But there is definitely a way to ignore a file in a Git repo: By adding the file(s)—including their relative path if needed—to a .gitignore file:

A .gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected; see the NOTES below for details.

Creating a basic .gitignore is fairly easy since it’s just a plain text file. So—for example—if I had a config.php file in your root you would do this; assuming you are using PHP but the concept applies for any setup. Also I am using Nano as my text editor in this example but feel free to use whatever text editor you normally use for this:

nano .gitignore

And just add that filename to that file:

config.php

Save it and now Git will simply ignore that file.

That said, what I like to do for setups like this is to keep a sample/example config neutered of sensitive specifics in the repository so I have some reference as to what the config file format is a file named something like this:

config.SAMPLE.php

That way you know exactly how the config.php file should be setup via config.SAMPLE.php and you can ensure that the actual config.php is never touched by Git.

Also, if you plan on showing off your code, you need to expect that someone will try to take that code and implement it on their own system in some way. Remember, we are not you and without a sample config file in your repo, folks won’t really understand how to implement the code on their own. Heck they might might even think you’re not competent because you didn’t provide a basic configuration example.

  • 11
    +1 for the correct answer and suggesting a sample configuration file. There are some libraries like Figaro for Ruby that kind of nudge you in this direction. You should have a sample file committed with values similar to real values so that the person who looks at your code knows what the environment should look like. Some platforms, like Heroku, use environment variables, so you might set your configuration to something such as database_url = Environment.DATABASE_URL and leave a comment above like # postgres://username:password@localhost/dbname. – Chris Cirefice Oct 26 '15 at 15:54
  • @ChrisCirefice Thanks! Always amazes me that new “tools” come around that should remind you of the obvious: If this code is going to be read by other humans, not explaining how a config works does what exactly? Thanks again. – JakeGould Oct 26 '15 at 17:04
27

You can also add a pre-commit hook to implement sanity checks. The directory .git/hooks of every git repository has some sample scripts.

The script called pre-commit is executed if it exists before each commit, and a non-zero return value aborts the commit.

For example, you could have a simple script like this:

#! /bin/sh -e
git ls-files --cached | grep -qx 'filename' && { echo "Excluded file included in the commit" >&2; exit 1; }
exit 0

And if that filename matches, the commit fails.

  • 1
    +1 this is the right answer that actually prevents explicitly adding & committing the file. – R.. Oct 27 '15 at 3:51
  • Indeed, although recommended practice is not to rely on having this prevention in place (i.e. use `.gitignore instead). – David Z Oct 27 '15 at 14:26
  • 2
    @R.. Yes and no. While the question states, “marking a file as being ucommitable” the spirit is “preventing a file from being committed.” The reality is creating .gitignore is very common—and commonly understood—practice for anyone using Git. But a pre-commit script isn’t really used by most users of Git. It requires some knowledge of setup and it requires some true reason why a method like this would be preferable to simply using a .gitignore file. But this is very useful for some more complex cases, but it’s definitely a concept you would use when you truly know you need to use it. – JakeGould Oct 27 '15 at 16:20
  • 2
    I could see using this in situations where you may not 100% trust .gitignore (you might do something foolish accidentally demand git add the file for comitting). Or perhaps someone else might edit the .gitignore file (it is under version control, after all). If you really need a testable process this is something you could work into such a process. – Cort Ammon Oct 28 '15 at 1:18
  • @CortAmmon it's not always about trust. You may add some temporary and non-public debug information to your source code that you don't want to commit but you cannot ignore such file. Instead you want to check it before commiting if it doesn't contain anything illegal. This looks like a good solution for this use case. And as a metter of fact this is how I found this question because it's my use case. – t3chb0t Oct 28 '18 at 11:11
12

What @JakeGould said. In some instances you could also make use of special file bits like skip-worktree or assume-unchanged that can be set the following way; for the differences between the two, see this Stack Overflow answer:

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

Which will then hide additional changes to an already existing file and which you could use if you really want a file to be there after every pull. But I would advise you to only use it if you really know what you are doing.

8

Use a .gitignore like @JakeGould said. In addition, some related info:

  • .gitignore keeps files from being tracked; if they are already tracked use git rm --cached to remove them
  • files/patterns in $GIT_DIR/info/exclude will also be ignored
  • files/patterns in the file specified by the core.excludesFile in the user’s ~/.gitconfig also are ignored.

See the official Git documentation for more details.

2

To extend on Jake and 46's answers: one very good practice is to have a consistent extension you use for files you include private information in, and use .gitignore to always exclude files with that extension globally (using the .gitconfig file as mentioned elsewhere to have it always ignored for your user).

That way, you can have for example:

/projectname/mypasswords.exc 

and if you've excluded *.exc globally, then you know it won't be committed, even if you forget to individually exclude that specific file.

protected by JakeGould Oct 26 '15 at 21:12

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.