Git: Ignore files for public repository, but not for private

Solution 1:

I will second the submodule answer, but try to provide some clarification. First, git does not deal with files but with commits. There is no way to filter files or paths in a branch because a branch is really a pointer to a commit. When you exclude or ignore you are just keeping files from being added to your repository. none of the 'sensitive files' files are even in the repository, just in your working directory.

The submodule is just a reference to another repository stored in your repository, and a specific commit that that checked out repository is tracking. you can say update using

git submodule update --recursive sensitive-files

In order to simplify things, you can commit symlinks in the proper place pointing to the submodule path.

ln -sf sensitive-files/shadow passwd

Then add the symlink as you would any other file..

Remember the submodule is just a checked out git repository, you can easily restrict access to that actual repository and make the main one public.

Updated:

Sorry I missed the notification, if you are still working on this.

You can have multiple symlinks in your private repository referencing the private repository (submodule) which is checked out in a subdirectory.Each of the databases or whatever used by the Rails instance could be a symlink into that private subdirectory.

Also, you don' t need a remote pointing to the private repository, just an entry in the .gitmodules file which is maintained automatically by git submodule. You would still need to protect the private repository so that only your Heroku instance could access it. For that I would suggest installing gitosis on a server if you can or use some other private git hosting solution. Add the public ssh key matching your instances private key tothe list of allowed users. (I'm not familiar with how to do this in Heroku.)

When you push your changes to heroku it should recursive download all the submodules mentioned in the repository.

Solution 2:

You could create a pre-commit hook in your local repo, in here you can write a script to check the currently checked out branch and delete the offending files if they are present before the commit is processed. This avoids the files ever being recorded in the Git history of the wrong branch.

#!/bin/bash
current_branch="$(git branch | sed -e 's/^*//')"
if [ $current_branch != "heroku" ]; then 
    // Delete sensitive files before commit
    rm -f dir1/dir2/exclude_from_public
    rm -f dir1/dir2/exclude_from_public_also
fi
exit 0

Alternatively, the script could just check for the files and return exit code "1", notifying you that the commit cannot proceed because it contains sensitive files.

The caveat is that you will need to hand this script to anyone who is working on the "privileged" heroku branch, and always have it included in your own local repo.

Ideally you would have this check done server-side as well; but unfortunately GitHub only offers a Web variant of the post-receive hook, so unless you do you're own repo hosting this approach can only be performed locally.

Solution 3:

One way to do this would be to put your private file(s) in a submodule, and refer to that module from your public repo. (Alternately, you could put your public files in a submodule, and refer to that repo from your private repo.)