🔄

複数Gitリポジトリを一括更新するシェルスクリプト

に公開
2026/08/30

はじめに

複数のGitリポジトリを管理していると、「全部mainブランチに戻して最新化したい」という場面がよくあります。

手動で一つずつ git checkout main && git pull するのは面倒なので、一括で処理するシェルスクリプトを作りました。

こんな人向け

  • 複数のプロジェクトを並行して開発している
  • featureブランチで作業後、mainに戻し忘れがち
  • 定期的に全リポジトリを最新化したい

スクリプト

#!/bin/bash
# Git一括更新スクリプト
# 説明: 全リポジトリをmainブランチに切り替えて最新化する
# (set -e は使わない。失敗したリポジトリを数えて続行し、最後に集計するため)

# カラー定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# ベースディレクトリ(スクリプトのある場所)
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"

# リポジトリ一覧(配下の.gitを自動検出)
REPOS=()
while IFS= read -r -d '' git_dir; do
    repo_path="${git_dir%/.git}"
    repo_rel="${repo_path#"$BASE_DIR"/}"
    REPOS+=("$repo_rel")
done < <(find "$BASE_DIR" -type d -name .git -prune -print0)

echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}  Git リポジトリ一括更新スクリプト${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""

# 成功・失敗カウンター
SUCCESS_COUNT=0
FAIL_COUNT=0

update_repo() {
    local repo=$1
    local repo_path="$BASE_DIR/$repo"

    echo -e "${YELLOW}----------------------------------------${NC}"
    echo -e "${BLUE}📁 $repo${NC}"

    # リポジトリが存在するか確認
    if [ ! -d "$repo_path/.git" ]; then
        echo -e "${RED}  ❌ Gitリポジトリが見つかりません${NC}"
        ((FAIL_COUNT++))
        return 1
    fi

    cd "$repo_path"

    # 現在のブランチを取得
    CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "")
    echo -e "  現在のブランチ: ${YELLOW}$CURRENT_BRANCH${NC}"

    # ローカル変更を確認
    if [ -n "$(git status --porcelain)" ]; then
        echo -e "  ${YELLOW}⚠️  ローカル変更あり - stash します${NC}"
        git stash push -m "Auto stash before update $(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
        STASHED=true
    else
        STASHED=false
    fi

    # mainブランチに切り替え(main以外にいる場合)
    if [ "$CURRENT_BRANCH" != "main" ]; then
        echo -e "  ${YELLOW}🔀 mainブランチに切り替え中...${NC}"
        if git checkout main 2>/dev/null; then
            echo -e "  ${GREEN}✓ mainに切り替えました${NC}"
        else
            echo -e "${RED}  ❌ mainブランチへの切り替えに失敗${NC}"
            ((FAIL_COUNT++))
            return 1
        fi
    fi

    # fetch & pull
    echo -e "  ${BLUE}🔄 fetch中...${NC}"
    if git fetch origin 2>&1; then
        echo -e "  ${BLUE}⬇️  pull中...${NC}"
        if git pull origin main 2>&1; then
            echo -e "  ${GREEN}✅ 更新完了${NC}"
            ((SUCCESS_COUNT++))
        else
            echo -e "${RED}  ❌ pullに失敗${NC}"
            ((FAIL_COUNT++))
        fi
    else
        echo -e "${RED}  ❌ fetchに失敗${NC}"
        ((FAIL_COUNT++))
    fi

    # stashを戻す
    if [ "$STASHED" = true ]; then
        echo -e "  ${YELLOW}📤 stashを復元中...${NC}"
        git stash pop 2>/dev/null || echo -e "  ${YELLOW}⚠️  stash復元に競合の可能性${NC}"
    fi
}

# 各リポジトリを更新
for repo in "${REPOS[@]}"; do
    update_repo "$repo"
    echo ""
done

# サマリー表示
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}  更新結果サマリー${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}  ✅ 成功: $SUCCESS_COUNT${NC}"
echo -e "${RED}  ❌ 失敗: $FAIL_COUNT${NC}"
echo ""
echo -e "${BLUE}完了しました!${NC}"

使い方

1. スクリプトを配置

プロジェクトの親ディレクトリに git-update-all.sh として保存します。

~/dev/
├── git-update-all.sh  ← ここに配置
├── project-a/         ← 自動検出される
├── project-b/         ← 自動検出される
└── apps/
    └── frontend/      ← 自動検出される

2. 実行権限を付与して実行

chmod +x git-update-all.sh
./git-update-all.sh

配下の .git ディレクトリを自動検出するため、リポジトリ一覧を手動で編集する必要はありません。

機能

機能 説明
リポジトリ自動検出 配下の .git ディレクトリを find で自動検出
自動ブランチ切り替え main以外のブランチにいる場合、自動でmainに切り替え
ローカル変更の保護 未コミットの変更がある場合、自動でstash→復元
カラー出力 成功/失敗が一目でわかる
サマリー表示 最後に成功・失敗数を表示

自動検出の仕組み

スクリプト配置ディレクトリ配下の .git フォルダを find で再帰的に検出します。

# リポジトリ一覧(配下の.gitを自動検出)
REPOS=()
while IFS= read -r -d '' git_dir; do
    repo_path="${git_dir%/.git}"
    repo_rel="${repo_path#"$BASE_DIR"/}"
    REPOS+=("$repo_rel")
done < <(find "$BASE_DIR" -type d -name .git -prune -print0)

ポイント:

  • find ... -print0 と read -d '' でスペースを含むパスにも対応
  • -prune で .git ディレクトリ内への再帰を防止
  • 相対パスに変換して見やすく表示

カスタマイズ例

masterブランチを使う場合

main を master に置き換えます。

if [ "$CURRENT_BRANCH" != "master" ]; then
    git checkout master 2>/dev/null
fi
git pull origin master 2>&1

検出の深さを制限する

ネストが深い構成で直下のリポジトリだけ更新したい場合は -maxdepth を使います。

done < <(find "$BASE_DIR" -maxdepth 2 -type d -name .git -prune -print0)

動作環境

OS 動作
macOS (Catalina以降) ✅
Linux (Ubuntu等) ✅
Windows WSL2 (Ubuntu) ✅

※ macOS標準のBash 3.2で動作確認済み。絵文字表示にはUTF-8対応のターミナルが必要です。

注意点

  • stashの競合が発生した場合は手動で解決が必要です
  • リモートへの認証(SSH鍵など)が設定済みである必要があります
  • mainブランチが無いリポジトリ(master運用など)は「切り替え失敗」として数え、次のリポジトリへ進みます。その際、直前にstashした変更は自動復元されないため、git stash list で確認してください
  • set -e を足すと、mainの無いリポジトリに当たった時点でスクリプト全体が終了し、残りのリポジトリが未処理のままになります(サマリーも出ません)

まとめ

配下のリポジトリを自動検出し、mainへの切り替えとpullを一括実行して結果を集計します。失敗したリポジトリはスキップして続行するので、週明けにまとめて最新化する用途に向いています。

GitHubで編集を提案

Discussion