git ls-files
はディレクトリを指定してもそのディレクトリ以下のすべての管理されているファイルを表示します。
シェルで使うls
の様にカレントディレクトリだけを表示したい時はちょっと工夫がいります。
また、ignoreされているファイルやファイルの状態も見たい、ということで それを実現するaliasについて。
現在のディレクトリで管理されているファイルのみを表示
how to
git ls-files
for just one directory level. - Stack Overflow
上にある答えを使って
1
|
|
とすれば現在のディレクトリで管理されているファイルのみを表示できます。
一番簡易にはこれで足りることが多いかと思います。
変更したあとに細かく見ようと思うとこれだとチョット足りません。
ls-files
には-t
といった状態を示すオプションもありますが、
これは引数の状態に合わせて表示されるだけで、
通常のls-files
であれば全てH
(tracked file that is not either unmerged or skip-worktree)になります。
変更が入っているファイルだけを表示したければ
git ls-files -m -t
とかするとC
と表示され、変更されたものでstagingされてないものだけが表示されます。
ただ、staged
な状態でmodified
とかの状態はわからないので全て何もしてないファイルと同等に見えてしまいます。
管理されてるディレクトリのみ表示
How to git list only the tracked directories? - Stack Overflow
上の最初の答えでは
1
|
|
となってますが、これだとdirname
なので下に多階層のディレクトリ構造があると上手くいきません。
直接cut -d '/' -f1
とかで良さそう。
そのままやるとカレントディレクトリのファイルも/
を含まないですがそのまま表示されてしまうので
1
|
|
とすれば必要なものが取得できます。
加えて、各ディレクトリの中に変更があるかどうかも見たい時、git status
の結果を見て
1 2 3 4 5 6 7 8 9 |
|
のように変更があるとstaged
とunstaged
でそれぞれで、
staged
:Changes to be committed:
unstaged
:Changes not staged for commit:
といった出力があります。
これを各ディレクトリ毎に見て、
以下で見るgit status -s
の表記と同じになるように
1 2 3 4 5 |
|
と、それぞれ何らか変更があればM
、なければスペースを表示するようにできます。
最近の通常のシェルスクリプトなら
1 2 3 |
|
のように書くことも可能で、こちらのほうがサブシェルに入らないので色々便利ですが、 この書き方はgitの中のシェルが理解してくれないのでaliasを書く際には上のようなパイプで繋いだ形でやる必要があります。
変更されたファイル、ignoreされたファイルの表示
git status -s
で現在のレポジトリ内の変更があったファイルに関して、staged
, unstaged
両方の状態を簡単に見ることができます。
1 2 3 |
|
とかならaは変更された後git add
されている状態、bは変更されたけどgit add
されていない状態です。
また、git mv
でrename
な状態にあると、
1 2 |
|
みたいな感じで表示されます。
さらに--ignored
オプションを加えると.gitignoreで指定されている除外ファイルも
1
|
|
のように!!
な状態として表示されます。
このgit stagus
でもls-files
同様に:(glob)*
を渡すことで現在のディレクトリのみを見ることが可能です。
ただし、1つだけとれないのが別のディレクトリからrename
されてきたもの。
cというファイルが他のディレクトリからgit mv
で持ってこられるとそのままだと
1 2 |
|
の様にrename
したことがわかりますが、元のファイルのディレクトリを除いた範囲で見てみると
1 2 |
|
と、単に新しく加えられたファイルのように見えてしまいます。
このrename
もきちんと捉えるためと、カレントディレクトリ中でignore、及びまだ追加されていないディレクトリ
も含めて取得するために以下のようなスクリプトを考えます。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
こんな感じに、git status
では全て表示させ、2列目とrenameがあった場合の4列目
を見てそれが/
を含まない、つまりカレントディレクトリのものであれば見るようなことができます。
while IFS=
と区切り文字を変更しているのは出力の最初にスペースがある可能性があるので、
元のIFSのままだとそこが消されてしまうのでそれを防ぐためにIFS=
として区切り文字をなくすことで
行ごとにそのまま扱うことができます。
また、各行でもgit status -s
だと最初にスペースがあるかないか、1列目と2列目で区切りがスペース1個か2個か分かれますが、
echo $line
でquoteしないと最初のスペースは消され、文字列中のスペースが複数あっても全て1つにまとまるので
後ろで簡単にcut
で区切れます。
スクリプトではまずstatusを表示されたファイル(及びディレクトリ)とそれがrenameされたものの場合にはrename先の名前を取得します。
最初のif文はそのどちらもがカレントディレクトリよい上のディレクトリにある場合にskipするもの(../
でスタートするものを除く)。
次のif文ではスラッシュが含まれないカレントディレクトリのファイル、及び最後がスラッシュになっているカレントディレクトリにあるディレクトリのみを抜き出して表示しています。
これに引っかからなかった時、rename先のファイルがあり、それがカレントディレクトリのファイルであれば表示しています。
空のディレクトリの検出
空のディレクトリはgitの管理下にはなりませんが、ignoreされてるわけでもunstagedな状態にあるわけでもありません。
なので上の作業では一切出てきませんが、とりあえずカレントディレクトリにあるディレクトリをパット表示するには
1
|
|
こんな感じで。
.gitディレクトリだけは手動で外します。
aliasにまとめる
ファイルを表示する
git ls-files ':(glob)*'
には変更があってgit status
に表示されるものも含まれるので、
まずgit status
から一覧を作り、その中にないものでls-files
で見つかったファイルを追加します。
git status
ではディレクトリはignoreされているもの、まだ追加されていないもののみが表示されるため、
git ls-files
では表示されません。
したがって上で作ったstatus込のディレクトリはそのまま追加します。
これを.gitconfigの[alias]
欄に追加出来る様に書き直すと
1 2 3 4 5 6 7 8 9 |
|
こんな感じに。
while
文はパイプを使う形にしているので中で変数を変更しても後で使えないため、echo
とかの出力を外側で変数に入れる必要がありますが、
これをするためにワンライナーにして$()
の中に突っ込んで、files
という変数の中に入れています。
最初にgit status
の結果。
次にgit ls-files
でカレントディレクトリのファイルを追加。
ここではfiles
をまず表示して、その中に無いものだけを選ぶようにfiles
の出力からawk '{print $2}
、及びawk '{print $4}'
で
ファイル部分、rename先を取得してそれらとの比較などを行って重複を除いています。
次にgit ls-files
を使ってカレントディレクトリないの管理されているディレクトリの追加。
最後に空のディレクトリの追加。ここではgit ls-files
の結果で最初のstatusが全部空のものもあるので直接awk
ではなくcut -c 4- | print '{print $1}'
で文字位置を見て抜き出すようなことをしています。
一番最後はファイル名の部分でソートして出力です。(2文字のstatus, 1文字のスペースがあるので、1番目のfield位置、つまり先頭から4文字目以降でソートする。)
もうちょっときれいな書き方も出来るかもしれませんがとりあえずこれで、
1
|
|
とすることで現在のディレクトリのファイルの状態をぱっと見ることができます。
以下のようなテストレポジトリで見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
git ls-here
すると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|