gitで、「トラッキング(追跡)していないブランチも全部プルする方法」を探していて見かけたコマンドを自分用に改良し、どういう操作をしているか分解してメモしてみます。
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. リモートの最新情報を取得
git fetch --all
すべてのリモートリポジトリから最新の情報を取得(fetch)します。この時点ではコードをプル・マージするなどの破壊的な影響をローカルブランチに与えません。
origin/main, origin/develop など、リモートの最新の状態がローカルのリモート追跡ブランチに反映されるだけで、ローカルの作業ブランチ(例:main, develop)は変更されないため安全に使用できます。
例えば、 git branch -r
などでリモートのブランチ一覧を表示しようとしても、リモートリポジトリにはあるはずのブランチが見えてこない時などに使えます。
2. リモートのブランチ一覧取得
| git branch -r
現在取得可能なリモートのブランチ一覧を表示します(例:origin/main, origin/develop, origin/feature/xxx など)。
3. シンボリックリンクを除外
| grep -v '\->'
HEAD -> origin/main
のようなシンボリックリンク的な表記を除外した結果だけをgrepします。
例えばひとつ前の手順でリモートのブランチ一覧取得が以下のような表示だった場合、
% git branch -r
origin/HEAD -> origin/main
origin/develop
origin/feature/123
origin/main
->
を含む行を除外した結果だけが取り出されます。
origin/develop
origin/feature/123
origin/main
要するに、正味のブランチ名だけを対象にしています。
4. リモートブランチ名をループで読み取り
| while read remote; do
各リモートブランチ(例:origin/develop)を1行ずつ読み取りループします。
5. ローカルブランチ作成&トラッキング設定
git branch --track "${remote#origin/}" "$remote"
git branch --track
は、指定したリモートブランチをローカルブランチとして作成し、トラッキング(追跡)の設定をします。
"${remote#origin/}"
は、リモートブランチ名(例:origin/feature/123)から origin/ を取り除いて、ローカルブランチ名にします(例:feature/123)。
$remote
は元のリモートブランチ名(例:origin/feature/123)です。
6. すべてのブランチをプル
| git pull --all
リモートリポジトリでの変更を、ローカルで対応するブランチへマージ(pull)しようとします。
つまり、「git fetch + git merge」を全リモートに対してあらためて実行します。
実行結果の例
リモートリポジトリ(origin)に以下のブランチがあるとします。
main
develop
feature/123
現在、ローカルに作成済みのブランチは一部のブランチのみで、情報を取得できているのも一部のリモートブランチのみです。
% 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
(作成済み)main → origin/main をトラッキング
(作成済み)develop → origin/develop をトラッキング
(新規作成)feature/123 → origin/feature/123 をトラッキング
考えられるこのコマンドの用途
- チーム開発で複数のブランチがリモートにあるが、自分のローカルにはまだない場合
- すべてのリモートブランチを一括でローカルに作成して追跡したいとき
- 環境構築初期やCI/CD関連のメンテナンス時に便利
注意点
既に存在するローカルブランチに対してはエラー(fatal:)が出ますが、「リモートリポジトリにある全ブランチをプルしたい」という要求に関しては動作に問題ありません。
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
[Git]リモートリポジトリの全ブランチをプルする