gitconfig shell-command aliasing runs from top-level rather than current directory
Asked Answered
P

2

3

I've written a bash script called git_diff_parent which, when passed a commit handle, performs git diff commit~1 commit; in other words, it diffs with its ancestor without having to specify commit~1 on the command line. I do this by parsing the git command line, finding which argument is the commit string (using git cat-file -t), replacing it with commit~1 commit then passing the new argument list to git diff. I've aliased this script in /etc/gitconfig so I can execute this command as git diff-parent:

[alias]
   diff-parent = !git_diff_parent

This almost works except when I try to diff an individual file from a place other than the top-level repository directory, e.g.:

% pwd
/home/myhome/github/my-branch/rtl
% git diff-parent branch -- mycode.sv
<no output>
% git diff-parent branch -- rtl/mycode.sv
<diff output appears>

To debug this, I added pwd to my script to see the script's working directory. Lo and behold, it always launches from the top-level directory (/home/myhome/github/my-branch) rather than the subdirectory I'm in. I've even tried git -C . diff-parent ... to no avail.

So is there any way to make my alias launch from the current working directory?

Premise answered 1/7, 2020 at 21:38 Comment(0)
M
2

https://git-scm.com/docs/git-config#Documentation/git-config.txt-alias

Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory. GIT_PREFIX is set … from the original current directory.

(Emphasize and cut are mine — phd)

So you can do cd $GIT_PREFIX in git_diff_parent shell script.

Maximilien answered 1/7, 2020 at 23:7 Comment(1)
Just what I needed. Thank you! One minor tweak: GIT_PREFIX is unset if you run from the top-level directory, so you need to catch that condition with something like cd ${GIT_PREFIX:-.} so it "changes" to the current directory in that case.Premise
S
0

To add to phd's answer:

GIT_PREFIX is set … from the original current directory.

Git 2.46 (Q3 2024), batch 12 as:

See commit 291ef5b, commit d35a743, commit 174443e (27 May 2024) by Ian Wienand (ianw).
(Merged by Junio C Hamano -- gitster -- in commit 718b50e, 10 Jun 2024)

Documentation: alias: add notes on shell expansion

Signed-off-by: Ian Wienand

When writing inline shell for shell-expansion aliases (i.e.
prefixed with "!"), there are some caveats around argument parsing to be aware of.
This series of notes attempts to explain what is happening more clearly.

git config now includes in its man page:

  • Shell command aliases always receive any extra arguments provided to the Git command-line as positional arguments.
    • Care should be taken if your shell alias is a "one-liner" script with multiple commands (e.g. in a pipeline), references multiple arguments, or is otherwise not able to handle positional arguments added at the end.
      For example: alias.cmd = "!echo $1 | grep $2" called as git cmd 1 2 will be executed as 'echo $1 | grep $2 1 2', which is not what you want.
    • A convenient way to deal with this is to write your script operations in an inline function that is then called with any arguments from the command-line.
      For example alias.cmd = "!c() {echo $1 | grep $2 ; }; c`" will correctly execute the prior example.
    • Setting GIT_TRACE=1 can help you debug the command being run for your alias.

The last part (debug trace) is enabled with:

run-command: show prepared command

Signed-off-by: Ian Wienand

This adds a trace point in start_command so we can see the full command invocation without having to resort to strace/code inspection.

For example:

$ GIT_TRACE=1 git test foo
git.c:755               trace: exec: git-test foo
run-command.c:657       trace: run_command: git-test foo
run-command.c:657       trace: run_command: 'echo $*' foo
run-command.c:749       trace: start_command: /bin/sh -c 'echo $* "$@"' 'echo $*' foo

Prior changes have made the documentation around the internals of the alias command execution clearer, but I have still found this detailed view of the aliased command being run helpful for debugging purposes.

Scrawly answered 31/7 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.