Git: ignore a file from a subtree, but track it locally and push it to a remote production

I have a quite specific workflow and the reason for that is that I use git subtree to include one project inside another:

It should look like this:

code
|--/.git
|--.gitignore
|--/styling
|  |--file1
|  |--file2.v1
|--file3
styling-bare
styling
|--/.git
|--.gitignore
|--file1
|--file2.v2

There are two use cases for the workflow:

  1. cd into styling, pull from styling-exchange, then cd into code, update the styling subtree, do some changes to file1 and file2 and file3, push to production
  2. cd into code, do some changes to file1 and file2 and file3, push changes to styling-bare (subtree push), cd into styling, pull from styling-bare, push changes to styling-exchange

I would like to have two completely different and separate versions of file2 in the local repositories styling/styling-bare VS the code/production repositories. I need to get all updates from the styling subtree into code/styling, but I need to track file2 just inside code, without any updates from styling.

I.e. I would like to update the styling subtree in the code repository, but keep my own version of file2 when I do that (while having file1 synced between styling and code and file3 synced between code and production), so that I can push my own version (v1) of file2 to production later.

Is there any elegant way to do that in git without symlinks or some sophisticated hooks?

Note, I have experimented with:

  • .gitignore file2 in the code repository: this does not work, the file is there once I do subtree pull to the styling subtree;

  • different .gitignore versions for different branches, but this breaks once I do merge;

  • I have tried to exclude file2 with .git/info/exclude_from_styling, this has no effect;

  • I have tried to remove file2 from index with git update-index --assume-unchanged styling/file2, but this does not solve my problem;

  • this solution will not work for me, because I will not be able to push all the styling directory to production;

  • I am not sure that a filter driver could help to solve the problem;

  • I need to keep the same name for file2 in all the repositories, so the solution with different names is not helpful either.

  • Git Submodules conflicting gitignore
  • Untrack git file
  • git status is showing “Changes not staged for commit” for files listed in .gitignore?
  • Heroku Cannot GET /
  • Uploading Specific Vendor files with Laravel's Envoyer
  • Git - git add in a gitignore directory
  • Git ignore file locally and always merge theirs
  • How can I version my .git/config file?
  • 2 Solutions collect form web for “Git: ignore a file from a subtree, but track it locally and push it to a remote production”

    Suggestions that come to mind :

    • Instead of a plain git subtree pull, you can use a script to pull the changes in your code repository, which would do something along the lines :

      git subtree pull ... && git checkout branch/with/my/specific/file2 -- styling/file2.v1

    • You can pull the changes from styling in a special branch used only for pulling, and merge the changes into your own branch. I haven’t tested it, but there should be ways to systematically say “keep my version of this file on merge” : tell git to use ours merge strategy on specific files

    I woudln’t exactly call this elegant, and each method has its flaws.

    You mentioned you wanted to avoid hooks, but you could also put the git checkout branch/with/my/specific/file2 -- styling/file2.v1 in a post-commit hook, or in a “smudger” on checkout (I just found out about git filters)

    1. If one is generated like a minification, you may consider having a script that automatically builds it. As a rule of thumb: Never, but never put generated code in a VCS.
    2. If v1 is the same file though as v2, use

      git diff <sha>..<sha>
      

      or you may even use a GUI (e.g. meld):

      git difftool <sha>..<sha>
      
    3. If you do not make changes to both of them, do not add the same project twice in your subtree, but use a script to get it any time you need it (the read-only version of it).

    It would help to know the languages, frameworks you’re using this project layout.

    Git Baby is a git and github fan, let's start git clone.