Delete unecessary .keep files

3.3k views Asked by At

I noticed my git repository has a lot of .keep files. They were once useful when their parent directories were otherwise empty, but since then a lot of the directories now have real children that keep them alive in git.

Is there a nice way to remove all unneeded .keep files? Particularly, those that:

  1. Have 0 size (no real content)
  2. Have precisely the name .keep
  3. Have neighbors in their folders (i.e. their deletion wouldn't lead to their parent folders becoming empty)

I looked at the docs of git gc, git clean, etc. but I didn't find such a feature.

3

There are 3 answers

3
zrrbite On

As you can read from Random 'concerns' folders and '.keep' files .keep files are just useful files to allow folders to be "committed" to a repository.

Here's a command to remove all .keep files. Then just commit that as you want afterwards.

zrrbite@ZRRBITE MINGW64 /d/dev/git/keeptest (master) 
$ git ls-files *.keep | xargs git rm                          
rm '.keep' 
rm 'test/.keep'
                                                         
zrrbite@ZRRBITE MINGW64 /d/dev/git/keeptest (master) 
$ git st                                                     
## master                                                    
D  .keep
D  test/.keep                                                 
0
terrorrussia-keeps-killing On

Git does not have any mention on what a keep file is, so its name is just a convention (.gitkeep, .keep, etc). This is why git-clean is does not support anything like that. I can't think of an extremely easy of doing that, so I ended up with a small script like this:

#!/bin/bash

# read all directories without escaping
while IFS= read -r DIR; do
    # enter to each directory to simplify parsing
    pushd "$DIR" 1> /dev/null
    # ask git to list all tracked files in the current directory
    #   filtering out the .keep file (the inVerted -v grep switch)
    #   and checking if it is giving more than 1 line
    if [[ $(git ls-files | grep -Pv '^.keep$' | head -1) ]]; then
        # if true, just print out the directory along with its "keep" file
        echo "$DIR/.keep"
    fi
    popd 1> /dev/null
    # the -mindepth would enable the depth-first traversing
    #   (empty files only named .keep and never walk into .git directories -- print out directories only)
done < <(find -mindepth 1 -not -path '*/\.git/*' -type f -name '.keep' -empty -printf '%h\n')

This script would print out all redundant .keep files in dry run. If the generated like looks fine, pipe it with xargs: above_script_path | xargs git rm

0
amtux On

Late to the party but you could run something like this which doesn't use git for tracked files but goes through all the directories:

find . -type d -exec sh -c '[[ $(ls -1A {} | wc -l) -gt 1 ]] && [ ! -s {}/.keep ] && rm -f {}/.keep' \;

find . -type d -exec sh -c '...' \;: Find all directories (recursive operation by default) and run the following shell command for that directory.

[[ $(ls -1A {} | wc -l) -gt 1 ]] && [ ! -s {}/.keep ] && rm {}/.keep': Run through each of the dirs and see if there are more than one files+directories located in them. If that is the case AND the file is empty, then delete .keep.