以下は社内向け勉強会のLT枠で話した内容をベースにして編集増補したものである。と言ってもgit addに関しては追加で書きたいこともあまりないので増補部分は少ない。
git addコマンドの概要
git addはワークツリーからインデックスへのファイルの登録を行うコマンドであり、それ以外の機能はほとんどない。
ワークツリーおよびインデックスの説明はgit checkoutの方で行っている。
git addの対象範囲
git add [--] <ファイル名>
で指定したファイルを対象としてインデックスに登録する。
ファイル名には複数指定、ワイルドカード、「.」(そのディレクトリとサブディレクトリにあるすべてのファイル、の意味)も指定可能である。「.」を使って「dir/.」のような指定も可能であり、この場合dirとそのサブディレクトリのすべてのファイルが対象になる。
ファイル名の直前の「–」はこの後の引数をオプションとして使用しない、という意味であり、ファイルパスがマイナスで始まるものを指定する場合に有用であるが、特にそういうのがなければ省略しても良い。習慣として付ける人もいるし、バッチの中で不特定のファイルを処理する場合は付けるべきだろう。
.gitignoreで指定されたファイルは対象外である。ただし-f(あるいは–force)オプションが指定されている場合は対象になる。
また、ファイルが新規追加されたものか更新されたものか削除されたものかのファイル状態ステータスを使用して対象範囲を絞り込むいくつかのオプションもある。
- -A(–all)
新規追加、更新、削除のファイルが対象になる。つまり、この点においてはオプションがない場合と同じである。オプションがない場合との違いはファイル名の指定を省略できることで、省略した場合リポジトリ内のすべてのファイルをファイル名に指定した場合と同じになる。つまりリポジトリ内のどこのディレクトリにいようとも、そのディレクトリとサブディレクトリだけを対象とする「.」とは違って、リポジトリ内のすべての新規追加、更新、削除が対象になる、ということである。
- -u(–update)
更新、削除のファイルが対象になり、新規追加のファイルは対象にならない。-Aと同様にファイル名を省略可で、その場合リポジトリ内のすべての更新、削除のファイルが対象となる。
- –no-all
新規追加、更新のファイルが対象となり、削除のファイルは対象にならない。ファイル名は省略できない。
上述の通りオプションなしのこれらのファイル状態ステータスでの範囲は-Aと同じであるが、かつては–no-allと同じであった。また、-Aや-uのファイル名を省略した場合は「.」を指定した場合は同じであった。これらの情報はWeb検索で古い記事を見ると書かれているが現在は変わっているので混乱しないように。
-N(あるいは–intent-to-add)という、更新のファイルには何もせず、削除のファイルは削除され、新規追加のファイルは空でインデックスに登録される、というオプションもある。このオプションはgit diff
で差分を表示させる対象にしたり、git commit -a
でコミット対象にしたりするのが目的である。-Nオプションで登録された新規追加のファイルは登録後に変更を行うと、もはや新規追加のファイルではなく更新のファイルである。
ファイル名を一覧で指定
「–pathspec-from-file 」オプションを指定した場合、直接ファイル名を指定する代わりに、このオプションで指定したファイルの中に書かれている、改行区切りのファイル名のリストを参照して、それらのファイルをインデックスに上げる対象にすることができる。
ここでファイル名に「-」を指定すると標準入力から取得するので、パイプ等で標準入力経由で対象となるファイルのリストを渡すことができる。
追加で–pathspec-file-nulオプションも指定すると、改行区切りではなくNUL文字区切りでファイルを読み込む。これはもはや完全に標準入力から読むつもりしかなさそうなオプションである。例えばfindの-print0オプションでNUL文字区切りのファイルのリストが返ってくるのでそれをパイプで渡す時に使用することになる。
なお、先に記事にしたgit checkoutあるいはgit restoreやgit resetにもこれらのオプションはあるのだが、使用頻度の面でgit addよりはかなり低いだろう。
ファイルの一部だけ追加する
git checkoutやgit restore等と同様に-p(あるいは–patch)オプションが存在するのでファイルの一部だけ追加することができる。
git checkout/git restoreの時との違いとして、以下のように各種メッセージの「discard」の部分が「stage」になっているのはともかく、
(1/1) Stage this hunk [y,n,q,a,d,s,e,?]? ?
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
eを押した時に入れる、エディタを立ち上げてdiffを編集するモードにて追加したい部分に「+」を付ければ良いのは、消す方に「+」を付けるgit checkout/git restoreと違ってわかりやすい。つまり、例えばインデックス側の今の内容が、
a
b
でワークツリーの内容が、
a
1
b
2
であり、最終的にインデックスを、
a
b
2
としたい場合、eで編集に入った先で次のように変更し、保存すれば良い(コメント行省略)。
@@ -1,2 +1,4 @@
a
+1
b
2
なお、git addには最初からエディタ立ち上げによるdiffを編集するモードにする-e(あるいは–edit)オプションもある。