12
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Git に ignore されているがビルドで必要なファイルを worktree に持ってくる

Last updated at Posted at 2025-11-30

アイデア

マルチエージェントでのコーディングにおいて、Git の worktree は有用である。

worktree を追加する際、.gitignore に指定されて Git の追跡対象外となっているディレクトリやファイルは無視される。

しかし、ビルド済みのフレームワークのような、ファイルサイズが大きく、かつビルドで不可欠なファイルこそ、往々にして .gitignore に指定されがちである。その場合、worktree での作業のためには、ひと工夫必要となる。

ファイルをコピーするのも手だが、ファイル数が大量であるか大容量ファイルが多ければ、処理に時間を要してしまう。

ならば、元のディレクトリやファイルへのシンボリックリンクを作成するのが良いのではないか。

考えた末、git worktree add の実行に加えて、引数で指定されたディレクトリやファイルについて、そのシンボリックリンクを worktree の作業ディレクトリ内に作成するシェルスクリプトを作成した。

コード

create_worktree_and_link.sh
#!/bin/bash
set -e  # エラーが発生したら停止

# 使用方法を表示
usage() {
    echo "Usage: $0 <branch_name> <worktree_path> <link_targets...>"
    echo ""
    echo "Arguments:"
    echo "  branch_name    : ブランチ名(既存または新規)"
    echo "  worktree_path  : worktreeを作成するパス"
    echo "  link_targets   : シンボリックリンクを作成するディレクトリまたはファイル(複数指定可)"
    echo ""
    echo "Example:"
    echo "  $0 feature/new-feature ../my-worktree node_modules .env DerivedData"
    exit 1
}

# 引数のチェック
if [ $# -lt 3 ]; then
    echo "エラー: 最低3つの引数が必要です"
    usage
fi

branch_name=$1
worktree_path=$2
shift 2
link_targets=("$@")

# Gitリポジトリのルートディレクトリを取得
repo_root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$repo_root" ]; then
    echo "エラー: Gitリポジトリ内で実行してください"
    exit 1
fi

echo "=== Worktree作成スクリプト ==="
echo "ブランチ名: $branch_name"
echo "Worktreeパス: $worktree_path"
echo "リポジトリルート: $repo_root"
echo "リンク対象: ${link_targets[*]}"
echo ""

# Step 1: Worktreeの作成
echo "Step 1: Worktreeを作成中..."
if git worktree add "$worktree_path" "$branch_name"; then
    echo "✓ Worktreeの作成が完了しました"
else
    echo "エラー: Worktreeの作成に失敗しました"
    exit 1
fi
echo ""

# worktreeの絶対パスを取得
worktree_abs_path=$(cd "$worktree_path" && pwd)

# カレントディレクトリを保存
original_dir=$(pwd)

# リポジトリルートに移動
cd "$repo_root"

# Step 2: シンボリックリンクの作成
echo "Step 2: シンボリックリンクを作成中..."

link_count=0
skip_count=0

for target in "${link_targets[@]}"; do
    # ソースパス(元のリポジトリ内)
    source_path="$repo_root/$target"
    # ターゲットパス(worktree内)
    target_path="$worktree_abs_path/$target"
    
    # ソースが存在するかチェック
    if [ ! -e "$source_path" ]; then
        echo "  警告: $target が見つかりません。スキップします。"
        ((skip_count++))
        continue
    fi
    
    # ターゲットパスの親ディレクトリを取得
    parent_dir=$(dirname "$target")
    
    # 親ディレクトリを作成(必要な場合)
    if [ "$parent_dir" != "." ] && [ ! -d "$worktree_abs_path/$parent_dir" ]; then
        mkdir -p "$worktree_abs_path/$parent_dir"
    fi
    
    # 既にリンクまたはファイルが存在する場合
    if [ -e "$target_path" ] || [ -L "$target_path" ]; then
        echo "  警告: $target は既に存在します。スキップします。"
        ((skip_count++))
        continue
    fi
    
    # シンボリックリンクを作成
    if ln -sf "$source_path" "$target_path"; then
        ((link_count++))
        if [ -d "$source_path" ]; then
            echo "  ✓ ディレクトリリンク作成: $target"
        else
            echo "  ✓ ファイルリンク作成: $target"
        fi
    else
        echo "  エラー: $target のリンク作成に失敗しました"
        ((skip_count++))
    fi
done

echo ""
echo "=== 処理完了 ==="
echo "✓ 作成されたリンク数: $link_count"
echo "✓ スキップされた数: $skip_count"
echo ""
echo "Worktreeは以下に作成されました: $worktree_abs_path"

# 元のディレクトリに戻る
cd "$original_dir"

使い方

chmod +x create_worktree_and_link.sh を実行し、スクリプトの実行権限を付与しておく

./create_worktree_and_link.sh [展開するブランチ名] [worktreeの展開先のディレクトリパス] [「一緒に持っていきたい」ディレクトリやファイルのパス(スペース区切りで複数指定可)]
12
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?