web-dev-qa-db-ja.com

位置パラメーターを持つGitエイリアス

基本的に私はエイリアスしようとしています:

git files 9fa3

...コマンドを実行するには:

git diff --name-status 9fa3^ 9fa3

ただし、gitはaliasコマンドに位置パラメーターを渡すようには見えません。私が試してみました:

[alias]
    files = "!git diff --name-status $1^ $1"
    files = "!git diff --name-status {1}^ {1}"

...および他のいくつかのものが動作しませんでした。

縮退ケースは次のようになります。

$ git echo_reverse_these_params a b c d e
e d c b a

...どうすればこの作品を作ることができますか?

236
user400575

最も明白な方法は、シェル関数を使用することです:

[alias]
    files = "!f() { git diff --name-status \"$1^\" \"$1\"; }; f"

!のないエイリアスはGitコマンドとして扱われます。例えばcommit-all = commit -a

!を使用すると、シェルで独自のコマンドとして実行され、このような強力な魔法を使用できます。

UPD
コマンドはリポジトリのルートで実行されるため、コマンドでファイル名を参照するときに${GIT_PREFIX}変数を使用できます

338
Cascabel

(関数を作成する代わりに)shを直接参照することもできます。

[alias]
        files = !sh -c 'git diff --name-status $1^ $1' -

(行末のダッシュに注意してください-必要になります。)

89
mipadi

探しているエイリアスは次のとおりです。

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 #は重要です。これにより、ユーザーが指定したすべての引数がシェルによって処理されなくなります(コメント化されます)。

注:gitは、ユーザーが指定したすべての引数をコマンドラインの最後に配置します。これを実際に見るには、GIT_TRACE=2 git files a b c dを試してください。

エスケープ(ネストのため)quotesは、スペースまたは"; rm -rf --no-preserve-root /;を含むファイル名にとって重要です。

72
Tom Hale

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を参照)。エイリアスに「#」を追加すると、末尾のパラメータを残さずに位置パラメータも許可されます。

24
bsb

Drealmerが述べたように 上記

" 注意してください、 !リポジトリのルートで実行されるため、エイリアスを呼び出すときに相対パスを使用しても期待した結果が得られません。 – Drealmer 13年8月8日16:28で"

GIT_PREFIXはgitによって現在のサブディレクトリに設定されているため、最初にディレクトリを変更することでこれを回避できます。

git config --global alias.ls '!cd "$ {GIT_PREFIX:-。}";ls -al'

17

私はこれを行うエイリアスでこれをしたかった:

git checkout $1;
git merge --ff-only $2;
git branch -d $2;

最後に、このコンテンツを持つ git-m という名前のシェルスクリプトを作成しました。

#!/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;

これには、muchより読みやすいという利点があります。複数行にあるためです。さらに、-xset -eでbashを呼び出すことができるのが好きです。おそらくこのすべてをエイリアスとして実行できますが、それは非常にく、保守が困難です。

ファイルの名前はgit-mなので、次のように実行できます:git m foo bar

8
Daniel Kaplan

似たようなものにぶつかりました。私のメモを投稿するのがOKであることを願っています。 gitエイリアスと引数とを混同する1つの理由は、おそらくgit help configにあります(gitバージョン1.7.9.5があります)。

エイリアス展開の前に感嘆符が付いている場合、シェルコマンドとして扱われます。たとえば、「alias.new =!gitk --all --not ORIG_HEAD」を定義すると、「git new」の呼び出しは、シェルコマンド「gitk --all --not ORIG_HEAD」の実行と同等になります。シェルコマンドは、リポジトリの最上位ディレクトリから実行されることに注意してください。これは、必ずしも現在のディレクトリであるとは限りません。 [...]

私がそれを見る方法-感嘆符を前に付けたときにエイリアスが「シェルコマンドとして扱われる」場合-なぜ関数を使用する必要があるのか​​、または引数で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エイリアスの! "as-is"の後に "plain"コマンドを使用している場合-gitはそのコマンドに引数リストを自動的に追加します!それを回避する方法は、実際、スクリプトを関数として、またはsh -cの引数として呼び出すことです。

ここでのもう1つの興味深い点は(私にとって)、シェルスクリプトでは、通常、自動変数$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!への1つの引数として文字列全体を「見た」ので、それを実行可能ファイルとして実行しようとしたためだと思います。それに応じて、"echo 'A' 'B'"をファイルとして検出できませんでした。

いずれにせよ、上記のgit help config引用のコンテキストでは、次のように記述する方がより正確であると推測します。 "...呼び出し" git new "は、シェルコマンドの実行と同等です。 「gitk --all --not ORIG_HEAD $ @」。$ @は、実行時にコマンドラインからgitコマンドエイリアスに渡される引数です。.. " OPの「直接」アプローチが位置パラメータでは機能しない理由も説明できると思います。

4
sdaau