You want automatic "snapshot-style" commits which squash down once you have a true commit to make.
Here is my rough idea:
- Treat masteras your "official" commit timeline and work in a feature branch. (This is a pretty orthodox workflow anyway.)
- Work in a so-called feature branch which takes automatic snapshots (via zsh precommand)
- When you are ready for a (human) commit, merge all the automatic snapshots from your feature branch into master with --squashand commit with an appropriate message.
This might require some aliases both in zsh and git but I think it could work. Here are some rough ideas, the key one being git merge --squash.  (Also, sorry, I only speak Bash.)
# I type this manually when I start work in the morning.
start-snapshotting () {
    git checkout -b auto-snapshots master
    PROMPT_COMMAND=git-snapshot
}
git-snapshot () {
    branch=`git symbolic-ref HEAD`
    [ "$branch" = "refs/heads/auto-snapshots" ] || return 1
    git add . && \
    git status > /dev/null &&
    git commit -m 'Automatic snapshot'
}
# Do a real commit that I am interested in preserving.
# Parameters are passed unmodified to "git commit"
commit () {
    git checkout master && \
    git merge --squash auto-snapshots && \
    git commit "$@" && \
    git branch -D auto-snapshots && \
    git checkout -b auto-snapshots master
}
# I type this when I am done coding.
stop-snapshotting () {
    unset PROMPT_COMMAND
    git checkout master && \
    git branch -D auto-snapshots
}
Keep in mind there will be tons of edge cases such as files you should have added to .gitignore and I am sure plenty of others. But I think it could work.