Search code examples
gitgitignore

Git Ignore to Keep Directory Structure but Ignore Files


Let's assume I have a dir structure like so:

app/
  uploads/
    .gitkeep
    images/
      .gitkeep
    videos/
      .gitkeep
    docs/
      .gitkeep

I want to keep the dir structure but not include the files within (except .gitkeep obviously). The docs say:

A slash followed by two consecutive asterisks then a slash matches zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.

So, I would expect this to do the trick:

/app/uploads/**
!/app/uploads/**/.gitkeep

This isn't working however. None of the subdirectories are being added.


Solution

  • Thanks to a suggestion from @RyPeck, I started down the path of a bash script. Ultimately, it ended up being best utilized as a simple git hook.

    Running git commit, the following script will execute before the commit message appears. This allows me to (A) ensure that the files within these uploads directories are removed from the git cache ("un-add") and (B) add/touch a .gitkeep file in each of the directories to maintain directory structure.

    .git/hooks/pre-commit

    #!/bin/sh
    
    # pre-commit
    
    ################################################################################
    # This is a site-specific hook to deal with locally-generated files that don't                  
    # belong in the repo while maintaining the directory structure. The dir 
    # './images' is primarily managed via the CMS. This little ditty will 
    # remove cached files within the './images' directories (recursively) 
    # and adds a '.gitkeep' file to each folder (to maintain dir structure in repo).
    ################################################################################
    
    keep=images
    
    cd `pwd`
    
    for cached in `find $keep -type d`
    do
        if [ -d $cached ]
        then
            touch $cached/.gitkeep
            git rm -r --cached --quiet --ignore-unmatch $cached
            git add -f $cached/.gitkeep # Force add with -f to deal with .gitignore conflicts
            chmod 600 $cached/.gitkeep
        fi
    done
    
    echo "Removed locally-generated files in '$keep'"
    
    exit 0