15

I have the following 1-liner that I use to see who might be a good candidate for help with a peice of code:

git log --pretty=short . | grep ^Auth | sort | uniq -c | sort -nr 

which lists authors in order of commits, it's crude but it works OK.

When I add it to my git config however, like this:

[alias] guru=!git log --pretty=short . | grep ^Auth | sort | uniq -c | sort -nr 

running

git guru 

Gives different results to running it from the command line.

stuart@beavis(rp):~/git/apps$ git log --pretty=short . | grep ^Auth | sort | uniq -c | sort -nr 710 Author: dave <dave@b2368a2b-315f-46b9-a0b0-05934f827f41> 415 Author: pete <pete@b2368a2b-315f-46b9-a0b0-05934f827f41> 402 Author: craig <craig@b2368a2b-315f-46b9-a0b0-05934f827f41> 

Compared to:

stuart@beavis(rp):~/git/apps$ git guru 859 Author: craig <craig@b2368a2b-315f-46b9-a0b0-05934f827f41> 813 Author: paul <paul@b2368a2b-315f-46b9-a0b0-05934f827f41> 798 Author: dave <dave@b2368a2b-315f-46b9-a0b0-05934f827f41> 

As Stefan Näwe notes below, aliases run in the root of your repository, is there any way to run the command on the directory I'm in, or specify?

2
  • 1
    Looks like you want git shortlog -sn by the way. Commented Jan 12, 2012 at 12:30
  • @patthoyts, add that as an answer & it'll get a tick! Commented Jan 12, 2012 at 16:58

4 Answers 4

24

is there any way to run the command on the directory I'm in, or specify?

Yes, there is. When you run a git command, your environment gets a GIT_PREFIX variable with the value of the relative path (from toplevel to the path before executing git) so what you need is prefix your git aliases (that run shell commands and need the right pwd) with cd ${GIT_PREFIX:-.} && .

Simple test, add this to your ~/.gitconfig

[alias] p = !pwd && cd \"${GIT_PREFIX:-.}\" && pwd 
Sign up to request clarification or add additional context in comments.

3 Comments

For an explanation of the ${GIT_PREFIX:-.} syntax, refer to: stackoverflow.com/a/16753536/79111.
For those wondering why we need to protect against the unset-or-blank case: if you run a git alias in the top lever directory of the repo, $GIT_PREFIX will expand to the empty string. cd with an empty string argument will error out; cd with no argument will go to your home directory. And on that last note, always quote your shell variables: cd "${GIT_PREFIX:-.}".
To clarify: re: shell variable quoting: cd ${GIT_PREFIX:-.} will do the wrong thing if your directories have spaces (or other $IFS characters) or globbing characters in them (unless the shell your Git calls on your system breaks backwards compatibility with Bourne-like shell behavior). That won't come up often, but if it ever does come up the unquoted variant is guaranteed to do the wrong thing. cd "${GIT_PREFIX:-.}" will always do what's intended. And then because git does its own interpretation of double-quote characters in aliases, we need \" instead of just ".
13

git's aliases using a shell command (i.e. prefixed by !) run in the toplevel of the working directory (where the .git lives). Simple aliases (without !) run at the current directory.

3 Comments

Thanks Stefan, this answered my original question, I've ammeded now to hopefully make it more useful to others in the same situation.
This is a fairly unintuitive Git behavior. Does anyone know how to run an alias in the current directory? Or if the current directory is available in an env var or something so that an alias can cd back to the right place before running?
@JimStewart see Andrei Neculau's answer above, it shows how to do just that :)
4

Looking at what you are doing you probably want to use git shortlog -sn instead as this does the task in question already.

git aliases do not all run at the toplevel. As described in the git config manual "Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory." So only shell commands get run at the top level. If you simply alias a git subcommand it will run at the current location. The following session log demonstrates this:

pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ git rev-parse --show-cdup ../../ pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ git config alias.cdup 'rev-parse --show-cdup' pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ git cdup ../../ pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ git config alias.cdup2 '!git rev-parse --show-cdup' pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ git cdup2 pat@FROG /c/src/WiRE.git/wdf/src (pt/wdf) $ 

Your example uses an alias command that starts with 'git'. If I try setting 'git rev-parse --show-cdup' as the alias it returns an error stating 'git is not a git command' so I suspect you actually had a exclamation mark too hence running it as a shell command, thus running from the toplevel.

Comments

0

Another option is to use the -C option to git in the alias. This worked for me:

[alias] guru=!git -C ${GIT_PREFIX:-.} log --pretty=short . | grep ^Auth | sort | uniq -c | sort -nr 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.