答案 0 :(得分:333)
答案 1 :(得分:87)
答案 2 :(得分:68)
您正在寻找的别名是:
files = "!git diff --name-status \"$1\"^ \"$1\" #"
使用参数验证:
files = "!cd -- \"${GIT_PREFIX:-.}\" && [ x$# != x1 ] && echo commit-ish required >&2 || git diff --name-status \"$1\"^ \"$1\" #"
final #
非常重要 - 它会阻止shell处理所有用户提供的参数(它会将其注释掉)。
注意:git
将所有用户提供的参数放在命令行的末尾。要查看此操作,请尝试:GIT_TRACE=2 git files a b c d
转义(由于嵌套)引号对于包含空格或"; rm -rf --no-preserve-root /;
的文件名很重要
答案 3 :(得分:24)
使用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
选项都以不同的方式干净地处理“$ @”参数(请参阅GIT_TRACE)。将“#”附加到别名也可以允许位置参数而不会留下尾随的参数。
答案 4 :(得分:16)
正如Drealmer above所述:
«小心,!将在存储库的根目录运行,因此在调用别名时使用相对路径将不会给出您可能期望的结果。 - Drealmer 2013年8月8日16:28»
GIT_PREFIX
由git设置到您所在的子目录中,您可以通过首先更改目录来避免这种情况:
git config --global alias.ls'! cd“$ {GIT_PREFIX: - 。}”; ls -al'
答案 5 :(得分:8)
我想用一个执行此操作的别名来执行此操作:
git checkout $1;
git merge --ff-only $2;
git branch -d $2;
最后,我创建了一个名为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
答案 6 :(得分:4)
刚碰到类似的东西;希望能发布我的笔记。关于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
带参数;为什么不按原样写我的命令?
我仍然不知道答案 - 但我认为实际上结果略有不同。这是一个小小的测试 - 将其放在.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/
...或:当您在!
别名中git
“之后使用”普通“命令时,git
会自动附加参数列表那个命令!实际上,一种避免它的方法是将脚本称为函数 - 或称为sh -c
的参数。
另一个有趣的事情(对我来说)是,在shell脚本中,人们通常希望自动变量$0
是脚本的文件名。但是对于git
别名函数,$0
参数基本上是指定该命令的整个字符串的内容(在配置文件中输入)。
这就是为什么,我想,如果你碰巧错误引用 - 在下面的例子中,那将是逃避外部双引号:
[alias]
# ...
fail = ! \"echo 'A' 'B'\"
... - 然后git
会失败(对我来说,至少)有些神秘的信息:
$ 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
“看到”整个字符串只是!
的一个参数 - 它试图将其作为可执行文件运行;相应地,它找不到"echo 'A' 'B'"
作为文件。
在任何情况下,在上面的git help config
引用的上下文中,我推测它更准确地说:“ ... ...调用”git new“等同于运行shell命令“gitk --all --not ORIG_HEAD $ @”,其中$ @是在运行时从命令行传递给git命令别名的参数。“。我认为这也可以解释为什么OP中的“直接”方法不适用于位置参数。