Exposition:
- I do not git commit all that often; only after a lot of work.
- I occasionally do stupid things, like 'rm -f blah.hpp' when I mean 'rm -f blah.cpp'
- I use zsh
- I would like to set something up in my zsh p开发者_如何学Gorecmd to do a "git add **/*; git commit -a -m 'auto log ...'"
Now, here's the issue: alot of these commits are spurious. At some future point (like 24 hours later), I would like to kill all these useless intermediate autocommits.
If your solution requires I slightly modify my git workflow -- that is okay. I am willing to introduce changes in order to have this autocommit setup.
You want automatic "snapshot-style" commits which squash down once you have a true commit to make.
Here is my rough idea:
- Treat
master
as 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
--squash
and 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.
With Git1.7:
- you could make your auto-commit with a message beginning by
fixup!
- every 24h, you could do a
git rebase --interactive --autosquash
in order to squash all the automatic commits and ignoring their log messages.
See here for more details.
Of course, once in a while, do an explicit commit with a relevant message (for "real" commits") when you begin a task: all the other "automatic" commits will be squashed against that first commit;
精彩评论