0

Most of the time, I commit with git commit -am, because all I've done to the project belongs to the commit I'm working on.

Only sometimes, there are some changes I do not want to commit, so I use git add -p to stage only what I really want. Trouble is, I'm so used to typing git commit -am that I usually end up doing it anyway. I then get a commit with stuff I didn't want, and have to laborously go back to HEAD^, and also re-do the add -p.

Clearly, when some changes have already been added manually, commit -am doesn't make sense anymore. Is there a way to prevent git from accepting the option in this case (or some alternative to -am that is just as convenient)?

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319

2 Answers2

0

Easier, quicker, more seductive. As tempting as git commit -am may be, you should train yourself to stay away from it. It's really meant for very simple (e.g. single-file) commits. Use the staging area to your advantage: take the time to compose the shot before you take a snapshot.

If this admonition isn't enough, and you need a little help to avoid git commit -am... Well, unfortunately, the Git API itself doesn't provide an easy way of "forbidding" a subset of its commands. One not very robust way, but that mostly does the trick, is to write a simple shell wrapper function for git that keeps an eye out for command-line arguments commit and -am, and takes measures when those arguments are used (same strategy as in this other answer.):

# Git wrapper forbidding 'git commit -am'
git() {
    if [ "$1" = "commit" -a "$2" = "-am" ]; then
        printf "'git commit -am' is currently disabled by your Git wrapper.\n";
    else
        command git "$@";
    fi;
}

Depending on your habits, you can of course refine this wrapper to make it more robust.

Community
  • 1
  • 1
jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • Another approach would be to add a pre-commit hook that asks for confirmation, but I don't think there is a way of telling that hook that the `-am` flag was used. – jub0bs Aug 31 '15 at 19:13
  • I'm afraid if it weren't for `-am`, my hands would just get used to type `git add . && git commit -m`, and I'd have the same problem again. – leftaroundabout Aug 31 '15 at 19:56
  • @leftaroundabout "Bad habits" die hard. Unless you're ready to edit the Git source and build yourself a custom version, I can't think of any other way than that outlined in my answer, though. – jub0bs Aug 31 '15 at 20:06
0

You can create a script file, git-cm, and put it in your PATH

#!/bin/sh

DIRTY=$(git status -s| grep -e "^[A-Z]")
if [ ! "$DIRTY" ]; then
    git commit "$@";
    exit 0;
else 
    echo "Rejected, files already manually added";
    exit 1;
fi

run this when you want to commit

git-cm -am "some message"

if you already have files manually added the script will reject the commit and abort the operation.

This is because in this case, git status -s yields a line starting with e.g.

M  file/Ive/just.added`

where without manual adding it's

 M file/Ive/just.added

instead (notice the leading space).

You may need to adapt according to your environment.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
joran
  • 2,815
  • 16
  • 18
  • That `egrep '^[A-Z]'` seems an awful hack, but oh well... it does the trick. Thanks! – leftaroundabout Aug 31 '15 at 20:39
  • One has to remember to use `git-cm` instead of `git`... How does that help, when one is already trying to remember not to use a certain command? Anyway, you may want to add the `--porcelain` flag to your `git status` command, for improved robustness. – jub0bs Sep 01 '15 at 06:02