#!/bin/bash4 -eC
# git-update-index-keeping-only - rm all but matching files. (Helps git-filter-branch.)
# Copyright (C) 2016 Ivan Zakharyaschev <imz@altlinux.org>
set -o pipefail
# bash (not /bin/sh) is needed for <().

usage()
{
cat <<'EOF'
git-update-index-keeping-only - rm all but matching files. (Helps git-filter-branch.)

Usage:

  git-update-index-keeping-only GIT-RM-OPTS <FILELIST

-q is a useful option (which is passed to git-rm).

It works relative to the current directory, as `git ls-files` without
--full-name and `git rm` do: the filepaths are relative to the current
directory, and when deleting, it sees only the files inside the
current directory.

Example:

FILES="$(git diff-tree "$SINCE": HEAD: \
   -r --name-only --diff-filter=MACRT)"
export FILES
git filter-branch \
   --index-filter 'echo "$FILES" | git-update-index-keeping-only -q'
EOF
}

case "$1" in
    -h|--help|--usage)
        usage
        exit 0
esac

FILELIST="$(cat)"
readonly FILELIST

git ls-files \
| { fgrep -v -x -f <(echo "$FILELIST") || [[ "$?" -eq 1 ]]; } \
| xargs -d$'\n' --no-run-if-empty git rm --cached "$@" --
