-1

I created the following alias on Windows 10 to issue a commit -am <commit message> command. I used the the $1 token to register an argument, but it is not working.

git config --global alias.cam 'commit -am $1'

Issuing the following command returns the error message below:

git cam "test commit"

Error Message:

fatal: paths 'test commit ...' with -a does not make sense

How do I make this work? I researched how to use arguments in git aliases, but none of the resources offers a simple solution to my problem. Thanks.

Raj Narayanan
  • 2,443
  • 4
  • 24
  • 43
  • 1
    Just `commit -am`. It puts the args you supply at the end of the rewritten command. – jthill May 14 '21 at 00:47
  • https://stackoverflow.com/search?q=%5Bgit-alias%5D+arguments – phd May 14 '21 at 00:51
  • @jthill That works, but now it just displays the untracked files when I issue ```git cam "test commit"```. Nothing is staged or committed. If I issue the add and commit commands separately, it works fine. Why is that? – Raj Narayanan May 14 '21 at 00:51

2 Answers2

1

This is the rule for Git beginners: do not use git commit -a.

This is the rule for advanced Git users: do not use git commit -a unless:

  • you would run git add -u before git commit, and
  • you know that the repository is not using a badly written pre-commit script that will misbehave in the presence of git commit -a.

From your comment:

@jthill That works, but now it just displays the untracked files when I issue git cam "test commit". Nothing is staged or committed. If I issue the add and commit commands separately, it works fine. Why is that?

The problem here is that git commit -a is not like git add followed by git commit. It's more like git add -u followed by git commit (but even then, still not exactly the same). Specifically, git add -u will only update files that Git already knows about. The u in -u stands for update, i.e., don't add any untracked files, but do update all tracked ones as appropriate.

You have an untracked file that you'd like to add. You must use git add without the -u option to do this. (Technically there are several other commands that could get you there, but git add is the one to use.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks for this feedback. I just used the following alias and it works: ```git config --global alias.cam '!git add . && git commit -m'```. And the command ```git cam "test commit"``` now works. – Raj Narayanan May 14 '21 at 01:22
  • Why doesn't the following alias work? ```git config --global alias.rma '!git config --global --unset alias.$1'```. Issuing ```git rma cam``` doesn't remove the ```cam``` alias but doing this works: ```git config --global --unset alias.cam```. – Raj Narayanan May 14 '21 at 03:18
  • With the `$1` variant, you're literally running `git config --global --unset alias.cam cam`. (Use `GIT_TRACE=1` in front of a shell command to have Git show you what it's doing.) Next, check [the `git config` documentation](https://git-scm.com/docs/git-config). Exercise: what does `--unset name.of.option value_regex` do, based on the documentation? What does the regular expression `cam` match? – torek May 14 '21 at 13:38
  • After doing the exercise, consider the following general rule. To make Git shell aliases behave, write them as *shell functions*, using the template: `alias = !f() { command1; command2 "$1"; shift; command3 "$@"; }; f`. Another exercise (fairly hard unless you've done some shell programming): what's going on here? (If you have not written programs in sh/bash, there's a lot of reading to do!) – torek May 14 '21 at 13:41
  • I did the following and it's working now. Thanks again for the feedback. ```git config --global alias.rma '!sh -c "git config --global --unset alias.$1"'``` – Raj Narayanan May 14 '21 at 19:00
  • @rajndev: That does work, yes. Note that passes all arguments to the `sh -c` command. What does `sh -c "echo foo" bar baz quux` do? (Try it and see, and/or read the `sh` documentation. Try it with `sh -c 'echo $@'` as well.) The function method is more efficient, too, because it spawns one `sh` to interpret the alias without spawning a second `sh -c` to run the command. – torek May 14 '21 at 19:07
0

One solution is to pass the aliased git command to a shell command. This way, the $1 argument will not be appended again to the end of the command, causing it to succeed.

git config --global alias.cam '!sh -c "git commit -am $1"'

Or simply leave out the $1 argument token:

git config --global alias.cam '!git commit -am'

But, keep in mind that commit -a only applies to tracked files that need their modifications staged. So a better approach would be:

git config --global alias.cam '!git add . && git commit -m'

Raj Narayanan
  • 2,443
  • 4
  • 24
  • 43