2

Exposition:

  1. I do not git commit all that often; only after a lot of work.
  2. I occasionally do stupid things, like 'rm -f blah.hpp' when I mean 'rm -f blah.cpp'
  3. I use zsh
  4. I would like to set something up in my zsh precmd 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.

anon
  • 41,035
  • 53
  • 197
  • 293
  • 1
    Revise your workflow to commit more frequently. Try not to do stupid things - it hurts. There are mechanisms in git to allow you to modify history; I'd have to go read up on what they are, but Google 'git squash commits'. – Jonathan Leffler Feb 24 '10 at 06:59
  • 1
    If you automatically commit everything, how do you intend to actually commit anything intentionally? – Greg Hewgill Feb 24 '10 at 07:35
  • I strongly recommend against automatic commits. But it's not clear what your question is, as doing automatic commits is pretty trivial. Are you asking about techniques for purging them from the repo? – William Pursell Feb 24 '10 at 07:41

2 Answers2

1

You want automatic "snapshot-style" commits which squash down once you have a true commit to make.

Here is my rough idea:

  1. Treat master as your "official" commit timeline and work in a feature branch. (This is a pretty orthodox workflow anyway.)
  2. Work in a so-called feature branch which takes automatic snapshots (via zsh precommand)
  3. 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.

JasonSmith
  • 72,674
  • 22
  • 123
  • 149
0

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;

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250