リモートリポジトリ上のすべてのブランチをプルするコマンド[完全版]

gitで、「トラッキング（追跡）していないブランチも全部プルする方法」を探していて見かけたコマンドを自分用に改良し、どういう操作をしているか分解してメモしてみます。

```bash:リモートリポジトリ上のすべてのブランチをプルするコマンド
git fetch --all | git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done | git pull --all
```

### 概要

#### git fetch --all

コマンドの冒頭では、すべてのリモートリポジトリから最新の情報を取得（fetch）します。

#### git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done

コマンドの中盤は、リモートリポジトリ上の全てのブランチを、ローカルにトラッキングブランチとして作成（--track）するための操作です。特に、ローカルでまだトラッキングしていないブランチも含めて、自動でトラッキングブランチを作成します。

#### git pull --all

その上で、最後のコマンドによって全てのブランチを対象としてプルしています。

## コマンドの分解と説明

### 1. リモートの最新情報を取得

```bash
git fetch --all
```

すべてのリモートリポジトリから最新の情報を取得（fetch）します。この時点ではコードをプル・マージするなどの破壊的な影響をローカルブランチに与えません。
origin/main, origin/develop など、リモートの最新の状態がローカルのリモート追跡ブランチに反映されるだけで、ローカルの作業ブランチ（例：main, develop）は変更されないため安全に使用できます。
例えば、 ```git branch -r``` などでリモートのブランチ一覧を表示しようとしても、リモートリポジトリにはあるはずのブランチが見えてこない時などに使えます。


### 2. リモートのブランチ一覧取得

```bash
| git branch -r
```
現在取得可能なリモートのブランチ一覧を表示します（例：origin/main, origin/develop, origin/feature/xxx など）。

### 3. シンボリックリンクを除外

```bash
| grep -v '\->'
```
```HEAD -> origin/main``` のようなシンボリックリンク的な表記を除外した結果だけをgrepします。

例えばひとつ前の手順でリモートのブランチ一覧取得が以下のような表示だった場合、

```bash
% git branch -r

  origin/HEAD -> origin/main
  origin/develop
  origin/feature/123
  origin/main
```

```->```を含む行を除外した結果だけが取り出されます。

```bash
origin/develop
origin/feature/123
origin/main
```

要するに、正味のブランチ名だけを対象にしています。

### 4. リモートブランチ名をループで読み取り

```bash
| while read remote; do
```
各リモートブランチ（例：origin/develop）を1行ずつ読み取りループします。

### 5. ローカルブランチ作成＆トラッキング設定

```bash
git branch --track "${remote#origin/}" "$remote"
```

```git branch --track``` は、指定したリモートブランチをローカルブランチとして作成し、トラッキング（追跡）の設定をします。

```"${remote#origin/}"``` は、リモートブランチ名（例：origin/feature/123）から origin/ を取り除いて、ローカルブランチ名にします（例：feature/123）。

```$remote``` は元のリモートブランチ名（例：origin/feature/123）です。

### 6. すべてのブランチをプル

```bash
| git pull --all
```

リモートリポジトリでの変更を、ローカルで対応するブランチへマージ（pull）しようとします。
つまり、「git fetch + git merge」を全リモートに対してあらためて実行します。


### 実行結果の例

リモートリポジトリ（origin）に以下のブランチがあるとします。

```bash
main
develop
feature/123
```

現在、ローカルに作成済みのブランチは一部のブランチのみで、情報を取得できているのも一部のリモートブランチのみです。

```bash
% git branch

* develop
  main
  
% git branch -r 

origin/HEAD -> origin/main
origin/develop
origin/main
```

冒頭のコマンドを実行すると、ローカルに以下のトラッキングブランチが作成された上で、すべてプルしてくれます。

```git fetch --all | git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done | git pull --all```

```bash
（作成済み）main         → origin/main をトラッキング
（作成済み）develop      → origin/develop をトラッキング
（新規作成）feature/123  → origin/feature/123 をトラッキング
```

#### 考えられるこのコマンドの用途

- チーム開発で複数のブランチがリモートにあるが、自分のローカルにはまだない場合
- すべてのリモートブランチを一括でローカルに作成して追跡したいとき
- 環境構築初期やCI/CD関連のメンテナンス時に便利

#### 注意点

既に存在するローカルブランチに対してはエラー（fatal:）が出ますが、「リモートリポジトリにある全ブランチをプルしたい」という要求に関しては動作に問題ありません。

```bash:結果表示例
fatal: a branch named 'develop' already exists
branch 'feature/123' set up to track 'origin/feature/123'.
fatal: a branch named 'main' already exists
```

自分は特別な事情がありこのようなコマンドを整備するに至りましたが、```git pull --all``` をするため破壊的かつ、リモートリポジトリにあるブランチは文字通りすべて（不要なものも含めて）ローカルに作成されるため、明示的目的がない限りは選択的に使用する方が良いでしょう。


#### 参考URL
[How do I fetch all Git branches? - Stack Overflow](https://stackoverflow.com/questions/10312521/how-do-i-fetch-all-git-branches/21591209#21591209)
[[Git]リモートリポジトリの全ブランチをプルする](https://akumachan.github.io/Git/[Git]%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E5%85%A8%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E3%83%97%E3%83%AB%E3%81%99%E3%82%8B/)