git alias for shell command to cd into git root not working as expected

kuhbmx9i  于 12个月前  发布在  Shell
关注(0)|答案(2)|浏览(137)

我尝试使用git rev-parse --show-toplevel在git根目录中定义cd的别名。
目前,我在.bashrc中使用它作为别名,它工作正常:

alias gitroot='cd "$(git rev-parse --show-toplevel)"'

字符串
但是我知道你可以使用git别名来运行shell命令,所以我想我应该把这个命令移到我的.gitconfig中,让我的文件更干净一些。
问题是,我不知道为什么我的别名不起作用。目前我在.gitconfig中的[alias]下有这个:

root = "!sh -c 'cd \"$(git rev-parse --show-toplevel)\"'"


但是当我运行git root时,我只是停留在当前目录中。
我已经尝试过其他shell别名,它们都工作正常,例如别名say = "!sh -c 'echo \"$0\"'"工作得很好:

$ git say hello
hello


不过我注意到类似的cd命令(cd = "!sh -c 'cd \"$0\"'")失败了:

~/repos/myproject$ git cd /home/
~/repos/myproject$


我不知道这是因为我的语法,还是因为git别名的问题,它不支持cd命令,或者完全是其他原因。
如果有帮助的话,我使用的是Git 1.7.9.5。

qojgxg4l

qojgxg4l1#

您的shell正在调用Git,而Git正在调用另一个shell来运行您的cd命令。此命令成功,这会更改子shell的工作目录,但不会更改Git的工作目录,也不会更改父shell的工作目录。
为了做到这一点,你需要在你的 * 当前 * shell中运行命令,这意味着调用Git将无法完成这一点。你必须继续使用shell别名。
为了说明,假设您有以下名为up.sh的shell脚本:

#!/bin/sh
cd ..

字符串
如果您以./up.sh的身份执行此脚本,那么从当前shell的Angular 来看不会发生任何变化,因为cd是在新的shell示例中执行的。但是,如果您以. up.sh的身份执行它,则会指示当前shell自行执行文件的内容,而不会产生子shell。在这种情况下,当前shell的工作目录将发生变化。
这就是这里的关键区别。使用Git别名类似于./up.sh方法,而shell别名类似于. up.sh方法。

eqzww0vc

eqzww0vc2#

作为@cdhowie explained,你不能在一个实际的Git别名中做到这一点。但是你可以用一种几乎与Git别名没有区别的方式来实现这一点,使用wrapper function

git() {
    if [[ "$*" == 'root' ]]; then
        local root
        root="$(git rev-parse --show-toplevel)" || return $?
        cd "$root" || return $?
    else
        command git "$@"
    fi
}

字符串
除了在PWD中访问Git repo的根目录之外,还有以下功能:

  • 使用local变量可以避免污染命名空间。
  • 在几个极端情况下做正确的事情:
  • 如果该命令失败,返回git rev-parse --show-toplevel退出代码(通常是因为您不在Git存储库中)。
  • 如果由于某种原因cd连接到根目录失败,则返回cd退出代码。
  • 显示上述命令的标准错误输出(如果其中任何命令失败),以用于调试目的。
  • git root以外的任何命令转发到git命令本身。

相关问题