#!/bin/sh -e # Create a commit or stage files via fzf selection # If the first arg is "add", files are staged rather than committed. # All remaining args are passed to git-commit # TODO fix broken prep-commit-msg hook when there is no unifying path fzfpipe() { # Take nul-separated input from git-status short/porcelain # and return a newline-separated list of selected files cut -z -c2- | git fzf-diff --read0 -d' ' --nth=2.. --bind='alt-enter:execute(nvim {2..})' \ --preview="test {1} != \? && git diff --color HEAD -U5 -- {2..} | $(git config interactive.diffFilter) || find {2..} -type f | xargs -I% diff --recursive --color=always -u /dev/null %" | cut -c3- } test $(git ls-tree HEAD . | wc -l) -gt 1 && wd=$PWD cd "$(git rev-parse --show-toplevel)" prefix="/tmp/git/fuzz" mkdir -p "$prefix" case "$1" in (add) shift git status -z --porcelain --no-renames --untracked-files=all $wd | grep -zv '^\\w ' | fzfpipe | git -c advice.addEmptyPathspec=false add --verbose --pathspec-from-file=- "$@";; (*) git status -z --porcelain --no-renames $wd | sed -z 's/^\\(\\w\\) / \\1/' | fzfpipe >"$prefix/files" git -c advice.addEmptyPathspec=false add --intent-to-add --pathspec-from-file="$prefix/files" git commit -v --only --pathspec-from-file="$prefix/files" "$@";; esac