Using git, how do I ignore a file in one branch but have it committed in another branch?

Viewed 90546

I've got a project that I'm deploying to Heroku. The source code tree includes a bunch of mp3 files (the website will be for a recording project I was heavily involved with).

I'd like to put the source code for it up on GitHub, but GitHub has a 300 MB limit on their free accounts. I don't want to use 50 MB of my limit on a bunch of mp3 files. Obviously, I could add them to the .gitignore file to keep them out of my repo.

However, I deploy to Heroku using git push heroku. The mp3 files must be present in the branch I push to Heroku so that they get get deployed.

Ideally, I'd like to .gitignore the mp3 files in my local master branch so that when I push that to GitHub, the mp3s are not included. Then I'd keep a local production branch that has the mp3s committed rather than ignored. To deploy, I would merge master into production, and then push the production branch to Heroku.

I can't get this to work right.

Here's an example of what I'm trying to do...

$ git init git-ignore-test
$ cd git-ignore-test
$ echo "*.ignored" >> .gitignore
$ git add .gitignore && git commit -m "Ignore .ignored files"
$ touch Foo.ignored

At this point, Foo.ignored is ignored in my master branch, but it's still present, so my project can use it.

$ git checkout -b unignored
$ cat /dev/null > .gitignore
$ git add Foo.ignored .gitignore && git commit -m "Unignore .ignored files"

Now I've got a branch with these files committed, as I want. However, when I switch back to my master branch, Foo.ignored is gone.

Anyone got any suggestions for a better way to set this up?

Edit: just to clarify, I want the mp3 files to be present in both branches so that when I run the site locally (using either branch) the site works. I just want the files ignored in one branch so when I push to GitHub they are not pushed as well. Usually .gitignore works well for this kind of thing (i.e. keeping a local copy of a file that does not get included in a push to a remote), but when I switch to the branch with the files checked in, and then back to the branch with the files ignored, the files vanish.

9 Answers

1. Summary

  1. I use Travis CI for deploying (it supports Heroku deployment)
  2. I add to my .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore
    

    Where misc — any folder, contains another .gitignore.

    mv UNIX command move file; overwrite, if file already exist.

When Travis CI deploy project, Travis CI will not push to deploying provider files and folders, that ignore in misc/.gitignore (not in the original .gitignore of sources).


2. Limitations

  1. This answer may not be suitable for all conditions of the author. But this answer answers the question “Using git, how do I ignore a file in one branch but have it committed in another branch?”
  2. I'm not Heroku user, my examples for GitHub, not for Heroku. Data of this answer works for me in GitHub, but may doesn't work on Heroku.

3. Relevance

This answer is relevant for April 2018. In the future, the data of this answer may be obsolete.


4. Demonstration

my real project.

Example of successful deployment.

4.1. Task

I deploy my project from src branch to dest branch of the same repository.

I want, that file PaletteMira.suricate-profile:

  • Local machine — exists for all branches,
  • src remote branch — not exists,
  • dest remote branch — exists.

If I correctly understood the author of the question, he have similar task.

4.2. src

sources branch — SashaYAML.

Part of .travis.yml:

before_deploy:
- mv misc/.gitignore .gitignore

deploy:
  provider: pages
  on:
    branch: SashaYAML
  keep-history: true
  skip-cleanup: true
  target-branch: SashaDevelop
  repo: Kristinita/PaletteMira
  github-token: $GITHUB_TOKEN
  committer-from-gh: true
  project-name: PaletteMira
verbose: true

Part of .gitignore:

*.sublime-snippet
*.suricate-profile

Part of misc/.gitignore

*.sublime-snippet

*.suricate-profile not in misc/.gitignore.

PaletteMira.suricate-profile not exists in this branch remotely, but exists locally.

4.3. dest

destination branch — SashaDevelop

Part of .gitignore:

*.sublime-snippet

*.suricate-profile not in misc/.gitignore.

PaletteMira.suricate-profile exists for this branch remotely and locally.

4.4. Steps to reproduce

I enable PaletteMira GitHub repository for Travis CI → I set environment variable $GITHUB_TOKEN with value — my GitHub token → I make any commit to my src branch.

If no errors, I must get expected behavior.

The original question is a little oder but I came across it since I've just written a medium article about it, I thought this might help someone.

I personally have solved this with Git hooks via husky - seems to be the easiest and most reliable solution.

Obviously, I suggest to read the article but here are the steps to reproduce

  • step 1: yarn add -D husky && yarn husky install
  • step 2: yarn husky add .husky/post-checkout
  • step 3: mkdir .husky/gitignores && cp .gitignore .husky/gitignores
  • step 4: touch .husky/gitignores/.gitignore_husky
  • step 5: copy and paste this gist content into .husky/post-checkout
Related