Gitにおける git add の使い分け

## In a nutshell
Gitで変更を記録するには，まずステージに追加する必要がある． `git add` は変更内容をステージに登録するためのコマンドである．代表的な `git add` の使い分けとその挙動の違いについて記述した．


## はじめに
Gitにおいて，今までは `git add  .` を使用していた(これが習慣的な当たり前だと思っていた)．しかし，レポジトリに関して問題があり，それに対して対処をする過程で，`git add -A`というコマンドも存在する事を知った．良い機会である為，`git add .` と `git add -A` の違いと，普段はどちらを使うべきかを考えたので，以下に記述した．


## 予想される読み手
 - Git について初学者である，または，何となくで利用をしてきた
 - Git の `add` コマンドについて理解したいと考えている
 - ステージについて，あまり分からないで利用をしてきた


## 事前理解

### Git におけるステージとは
ステージとは，Gitがファイルの変更を一時的に記録する「インデックス領域」のことを指す．ユーザーが作業ディレクトリで行った変更は，直接リポジトリに反映されるのではなく，まずステージに追加され，その後 `git commit` によってリポジトリに保存される．この仕組みにより，どの変更をコミットするかを選択的にコントロールすることが可能となる．

### `add` の役割
`git add` は，作業ディレクトリで行った変更をステージに追加するためのコマンドである．この操作によって，変更が「次のコミット対象」として登録される．また，`add` はファイルを新規に追加する場合だけでなく，変更・削除した内容を明示的にステージする際にも使用される．



### ステージとコミットの関係
以下のような流れで，変更はGitのリポジトリに反映される：
```txt
作業ディレクトリ -> ステージ（インデックス） -> コミット（ローカルリポジトリ）
```
このフローにより，変更内容を一度「確認・選別」してからコミットすることが可能となる．



## 各コマンドの詳細

### `git add .`
- 現在のディレクトリおよびその配下にあるファイルの変更をステージに追加する．
- 対象となる変更:
  - 新規に追加されたファイル：追加される
  - 既存ファイルの変更：追加される
  - 削除されたファイル：無視される（ステージに追加されない）

このコマンドは，特定のサブディレクトリのみを操作したい場合や，カレントディレクトリ以下の限定的な変更のみを扱いたい場合に適している．


### `git add -A`（または `git add --all`）
- すべてのディレクトリにおける変更をステージに追加する．
- 対象となる変更:
  - 新規に追加されたファイル：追加される
  - 既存ファイルの変更：追加される
  - 削除されたファイル：追加される（削除の事実がステージに反映される）

すべての変更を確実にステージに反映させたい場合は，このコマンドの使用が推奨される．



### `git add -u`

- 変更されたファイルと削除されたファイルのみをステージに追加する．
- 対象となる変更:
  - 新規に追加されたファイル：対象外（ステージされない）
  - 既存ファイルの変更：追加される
  - 削除されたファイル：追加される

新規ファイルをまだステージしたくない場合や，既存のファイルに対する操作のみを反映させたい場合に有効．


### `git add <ファイル名>`

- 指定したファイルのみをステージに追加する．
- 対象となる変更:
  - 指定されたファイルに関する追加，変更，削除がステージに反映される

誤って不要なファイルを追加したくない場合や，コミット対象を明示的に制御したい場合に使用する．


## コマンド比較表

| コマンド            | 新規ファイル | 変更 | 削除 | 対象範囲                   |
|---------------------|--------------|------|------|----------------------------|
| `git add .`         | ○            | ○    | ×    | カレントディレクトリ以下     |
| `git add -A`        | ○            | ○    | ○    | プロジェクト全体（ルート基準） |
| `git add -u`        | ×            | ○    | ○    | プロジェクト全体（ルート基準） |
| `git add <file>`    | ○            | ○    | ○    | 指定ファイルのみ             |



## 使い分けの指針
以下に，使用シーンごとの推奨コマンドを示す．

| 使用シーン                           | 推奨されるコマンド     |
|------------------------------------|------------------------|
| すべての変更を確実に反映したい       | `git add -A`           |
| 一部のディレクトリのみ反映したい     | `git add .`            |
| 新規ファイル以外の変更のみ反映したい | `git add -u`           |
| 明示的にファイルを指定して追加したい | `git add <ファイル名>` |



## 備考

### ステージ内容の取り消し

- `.gitignore` に記述されたファイルは，いずれの `git add` コマンドでもステージ対象外となる．
- 誤ってステージした内容は，以下のコマンドで取り消すことができる：

```bash
git reset

```


### 環境による違い
一部のGitクライアント（GUIツールなど）では，`git add` の挙動が異なるように見える場合があるが，内部的には同じステージ操作が行われている．また，Gitのバージョンや，初期設定（`core.autocrlf` など）の違いにより，行末文字やファイルの検出に差異が生じることがある．


### `add`に関するエラーと対処方法
`git add` の実行時に発生するエラーには，パーミッションの問題や `.gitignore` による除外設定が影響していることがある．たとえば，追加しようとしたファイルが `.gitignore` によって無視されている場合，警告が表示されることがある．また，ファイルシステムのアクセス権限によってステージできないこともある．エラーが発生した場合は，`git status` や `git check-ignore` などのコマンドを用いて状況を確認するとよい．


### なぜ作業ディレクトリの内容を直接 `commit` できないのか
Gitでは，作業ディレクトリでの変更を直接コミットすることはできない．その理由は，**コミット対象の変更を選択的に管理できるようにするため**である．例えば，同時に複数のファイルを編集したが，コミットは一部のファイルに限定したいといったケースが存在する．ステージの存在によって，ユーザーは「どの変更を記録するか」を柔軟に制御できるようになっている．


### ステージに追加されたかを確認する：`git status`
変更がステージに追加されたかを確認するには，以下のコマンドを使用する：

```bash
git status
```

このコマンドにより，
- ステージされているファイル（緑色で表示）
- ステージされていないファイル（赤色で表示）
が一覧として表示される．ファイルの状態を視覚的に把握できるため，コミット前に確認する習慣を持つことが望ましい．

---

### `git restore --staged` によるステージの取り消し
ステージに追加した変更を取り消したい場合，以下のコマンドも有効である：

```bash
git restore --staged <ファイル名>
```

このコマンドは，指定したファイルをステージから取り除くが，作業ディレクトリ上の変更内容は保持される．`git reset` 全体を対象にするのではなく，ファイル単位で制御したい場合に便利である．



## Summary

- `git add` はステージに変更を追加するためのコマンドである．  
- `git add -A` はすべての変更（追加・変更・削除）を対象とする．  
- `git add .` は削除を除く変更をカレントディレクトリ以下に適用する．  
- `git add -u` は新規ファイルを除き，変更・削除のみを対象とする．  
- 使用目的に応じて，適切な `add` コマンドを選択することが重要である．



## Reference
 - [Git公式ドキュメント　git add](https://git-scm.com/docs/git-add)
 - [Atlassian Git Tutorials - Saving changes in Git](https://www.atlassian.com/git/tutorials/saving-changes)