Git别名与位置参数
基本上我试图别名:
git files 9fa3
执行命令:
git diff --name-status 9fa3^ 9fa3
但是git并没有将位置parameter passing给别名命令。 我努力了:
[alias] files = "!git diff --name-status $1^ $1" files = "!git diff --name-status {1}^ {1}"
…和其他一些人,但没有工作。
退化的情况是:
$ git echo_reverse_these_params abcde edcba
…我怎么做这个工作?
最明显的方法是使用shell函数:
[alias] files = "!f() { git diff --name-status \"$1^\" \"$1\"; }; f"
别名没有!
被视为Git命令; 例如commit-all = commit -a
。
随着!
,它在shell中作为自己的命令运行,让你使用这样更强大的魔法。
你也可以直接引用sh
(而不是创build一个函数):
[alias] files = !sh -c 'git diff --name-status $1^ $1' -
(注意行尾的破折号 – 你会需要的。)
您正在寻找的别名是:
files = "!git diff --name-status \"$1\"^ \"$1\" #"
通过参数validation:
files = "![ x$# != x1 ]&&echo "commit-ish required" >&2 || git diff --name-status \"$1\"^ \"$1\" #"
最后的#
很重要 – 它阻止了shell处理所有用户提供的参数(它将它们注释掉)。
注意: git
将所有用户提供的参数放在命令行的末尾。 要看到这个动作,请尝试: GIT_TRACE=2 git files abcd
转义(由于嵌套) 引号对于包含空格的文件名很重要,或者"; rm -rf --no-preserve-root /;
)
使用git手册页中描述的GIT_TRACE = 1来使别名处理透明:
$ git config alias.files !git diff --name-status $1^ $1 $ GIT_TRACE=1 git files 1d49ec0 trace: exec: 'git-files' '1d49ec0' trace: run_command: 'git-files' '1d49ec0' trace: run_command: 'git diff --name-status $1^ $1' '1d49ec0' trace: exec: '/bin/sh' '-c' 'git diff --name-status $1^ $1 "$@"' 'git diff --name-status $1^ $1' '1d49ec0' trace: built-in: git 'diff' '--name-status' '1d49ec0^' '1d49ec0' '1d49ec0' trace: run_command: 'less -R' trace: exec: '/bin/sh' '-c' 'less -R' 'less -R' MM TODO
您的原始命令与git 1.8.3.4版本一起工作(Eimantas在1.8.2.1中指出了这一点)。
sh -c '..' --
和f() {..}; f
f() {..}; f
选项以不同的方式干净地处理“$ @”参数(参见GIT_TRACE)。 追加“#”到一个别名也将允许位置参数而不离开尾随的参数。
如上面的Drealmer所述( https://stackoverflow.com/a/3322412/2955802 )
“ 小心, ! 将运行在版本库的根目录下,所以在调用你的别名时使用相对path不会给你所期望的结果。 – Drealmer 13年8月8日在16:28»
Git_PREFIX被git设置到你所在的子目录,你可以通过改变目录来绕过这个:
git alias ls ='! cd $ {GIT_PREFIX: – 。}; ls -al'
我想用别名做到这一点:
git checkout $1; git merge --ff-only $2; git branch -d $2;
最后,我创build了一个名为git-m的shell脚本,它具有以下内容:
#!/bin/bash -x set -e #by naming this git-m and putting it in your PATH, git will be able to run it when you type "git m ..." if [ "$#" -ne 2 ] then echo "Wrong number of arguments. Should be 2, was $#"; exit 1; fi git checkout $1; git merge --ff-only $2; git branch -d $2;
这有一个好处,它更清晰,因为它在多行。 另外我喜欢用-x
和set -e
来调用bash。 你也许可以把这个事情做成一个别名,但是这将是超级难看的,难以维护。
因为这个文件被命名为git-m
你可以像这样运行它: git m foo bar
刚碰上类似的东西, 希望这是奥克张贴我的笔记。 有一件事让我对使用参数的git
别名感到困惑,可能来自git help config
(我有git 1.7.9.5版本):
如果别名扩展以感叹号为前缀,则将被视为shell命令。 例如,定义“alias.new =!gitk – all – not ORIG_HEAD”,调用“git new”相当于运行shell命令“gitk – all – not ORIG_HEAD”。 请注意,shell命令将从存储库的顶级目录(可能不一定是当前目录)执行。 […]
我看到它的方式 – 如果一个别名“将被视为一个shell命令”的前缀感叹号 – 为什么我需要使用一个函数,或sh -c
与参数; 为什么不直接写我的命令呢?
我仍然不知道答案,但我认为结果实际上有些微差别。 这里有一个小testing – 扔在你的.git/config
或~/.gitconfig
:
[alias] # ... ech = "! echo rem: " shech = "! sh -c 'echo rem:' " fech = "! f() { echo rem: ; }; f " # must have ; after echo! echargs = "! echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ " fechargs = "! f() { echo 0[[\"$0\"]] 1-\"$1\"/ A-"$@"/ ; }; f "
这是我运行这些别名:
$ git ech word1 word2 rem: word1 word2 $ git shech word1 word2 rem: $ git fech word1 word2 rem: $ git echargs word1 word2 0[[ echo 0[["$0"]] 1-"$1"/ A-$@/ ]] 1-word1/ A-word1 word2/ word1 word2 $ git fechargs word1 word2 0[[ f() { echo 0[["$0"]] 1-"$1"/ A-$@/ ; }; f ]] 1-word1/ A-word1 word2/
…或者:当你使用“plain”命令后!
git
alias中的“as-is” – 然后git
自动将参数列表附加到该命令! 一种避免这种情况的方法确实是将脚本称为函数 – 或者作为sh -c
参数。
另一个有趣的事情(对我来说)是,在一个shell脚本中,通常需要自动variables$0
作为脚本的文件名。 但是对于一个git
别名函数, $0
参数基本上是指定该命令的整个string的内容(如在configuration文件中input的那样)。
这就是为什么我猜,如果你碰巧错误的 – 在下面的情况下,这将是逃避外双引号:
[alias] # ... fail = ! \"echo 'A' 'B'\"
… – 然后git
会失败(对我来说,至less)有些神秘的信息:
$ git fail "echo 'A' 'B'": 1: echo 'A' 'B': not found fatal: While expanding alias 'fail': ' "echo 'A' 'B'"': No such file or directory
我想,因为git
“看到”整个string只是一个参数!
– 它试图运行它作为一个可执行文件; 并相应地找不到"echo 'A' 'B'"
作为文件。
在任何情况下,在上面的git help config
引用的上下文中,我推测这是更准确的状态像这样:“ …调用”git new“相当于运行shell命令”gitk –all – -not ORIG_HEAD $ @“,其中$ @是在运行时从命令行传递给git命令别名的参数。 ” 我认为这也可以解释为什么OP中的“直接”方法不适用于位置参数。