10

Let's say that I have a command git branch (always with a couple of words) for example.

What I want is to keep track of when this command is executed with arguments. For example, if I execute the command git branch develop without errors, I want to save develop on a file.

I tried to overwrite git command on my .bash_profile, something like this:

git () {
    if [ $# -eq 3 ]
    then
        git $@
        echo $2 > /path/tacked_parameters.txt
    else
        git $@
    fi
}

But seems that does not work well. Is there any way to do this?

  • according to your example (git branch develop) you want to check if "$#" is "2" and not "3" ? ... (2 parameters to the git function) – Olivier Dulac May 12 '15 at 15:44
  • Was a mistake, but the code is just an example – jherran May 12 '15 at 15:46
  • ok. I added additional remarks underneath Stephane's (good) answer. my remarks may not be applicable (I think of the .txt as a log file, but it could be something else that can't have dates in it?) – Olivier Dulac May 12 '15 at 16:01
18

You've got a few problems here:

  • your git function is calling itself recursively instead of the original git command.
  • you're using $@ unquoted which doesn't make any sense whatsoever
  • you're leaving other variables unquoted, asking the shell to split+glob them.
  • you're using echo for arbitrary data.
  • you're losing the exit status of the original git command.
  • you're overwriting your log file upon each invocation.
  • you're putting function definitions in your ~/.bash_profile which is meant to customize your login session, not your shell and is normally not read by non-login bash invocations.

You'd want something like:

git() {
  if [ "$#" -eq 3 ]
  then
    local ret
    command git "$@"; ret=$?
    printf '%s\n' "$2" >> /path/tacked_parameters.txt
    return "$ret"
  else
    command git "$@"
  fi
}

That is:

  • quote your variables,
  • use command to run the git command,
  • save the exit status of git in a local variables an return it on exit,
  • use >> instead of > for redirection to the log file.
  • use printf instead of echo.
  • and put that in your ~/.bashrc instead (making sure your ~/.bash_profile is sourcing ~/.bashrc as login bash shells don't read ~/.bashrc by default (a bash bug/misfeature)). Unless you want to export that git function (with export -f git) in case you also want bash scripts that call git to call that function.
  • 1
    Amazing explanation and works like a charm. Thank you very much. – jherran May 12 '15 at 12:35
  • +1 for a very good answer. But the op may need to change the check to [ "$#" -eq 2 ] , according to his example. And it could be a good idea to also add the date to "tacked_parameters.txt". And I'd go for the general case (ie, not just track of the 2nd parameters when 2 parameters, but track any parameters) : I'd get rid of the if, and have: printf '%s: %s\n' "$(date '+%Y-%m-%dT%H:%M:%S')" "$0 $*" ? (ie, show the command + all the parameters (note that you still lose some info, for example which parameter's had intra-separators, if any). Portable date close to the iso8601 standard) – Olivier Dulac May 12 '15 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.