Claude Codeにコードを編集してもらうとき、「AIが作業する場所」と「自分が確認してGitHubへpushする場所」を分けたいと思ったことはありませんか。
私はいま、同じGitHubリポジトリをローカルに2つクローンし、次のように使い分けています。
- 作業用クローン:Claude Codeに編集・変更・ローカルコミットをしてもらう
- 反映用クローン:自分で差分を確認し、取り込んでテスト・pushする
実際に運用してみると、AIによる変更と自分の確認作業の境界が明確になり、とても役立っています。
この記事では、Ubuntu系LinuxとGitHubのHTTPS URLを使い、既存の develop ブランチへ直接コミットする構成を紹介します。
この運用でやりたいこと
流れはシンプルです。
Claude Codeが作業する場所
┌─────────────────────────────┐
│ 作業用クローン:repo-work │
│ │
│ 編集・動作確認・コミット │
│ GitHubへはpushしない │
└──────────────┬──────────────┘
│
│ ローカルからfetch
▼
自分が確認して反映する場所
┌─────────────────────────────┐
│ 反映用クローン:repo-publish │
│ │
│ 差分確認 → 取り込み → テスト │
│ GitHubへpush │
└──────────────┬──────────────┘
│
│ push
▼
GitHubリポジトリ
ポイントは、コミットとpushを分離することです。
作業用でコミットしても、それだけでGitHubへ反映されるわけではありません。GitHub側のブランチを更新するのはpushです。この違いを利用して、ローカルコミットを人間が確認するための受け渡し単位として使います。
なぜ2つのクローンに分けるのか
私の場合、Claude Codeに作業を任せつつ、GitHubへ送る変更は自分で確認したい、という目的がありました。
1つのディレクトリで編集と反映を行うこともできますが、場所を分けると、次の役割分担を意識しやすくなります。
| 場所 | 主な担当 | 役割 |
|---|---|---|
| 作業用クローン | Claude Code | 編集、動作確認、ローカルコミット |
| 反映用クローン | 自分 | 差分確認、取り込み、テスト、push |
| GitHub | チーム | 共有、レビュー、CI、履歴管理 |
企業のOrganization配下にあるプライベートリポジトリで開発する場合にも、「AIに作業してもらう段階」と「共有リポジトリへ反映する段階」を分ける運用として、相性がよいと感じています。
ただし、これは作業手順の分離です。ディレクトリを2つに分けるだけで、認証情報やアクセス権が分離されるわけではありません。この点は後半で説明します。
前提
この記事では、次の構成を使います。
GitHubリポジトリ:
https://github.com/ORG/REPO.git
作業用クローン:
~/projects/repo-work
反映用クローン:
~/projects/repo-publish
対象ブランチ:
develop
- OS:Ubuntu系Linux
- GitHubへの接続:HTTPS
- 作業用と反映用は、同じPCに配置
- 両方とも同じGitHubリポジトリからクローン
-
developブランチが既に存在する
ORG、REPO、ディレクトリ名は、自分の環境に置き換えてください。
1. 同じリポジトリを2つクローンする
mkdir -p ~/projects
# Claude Codeが作業する場所
git clone https://github.com/ORG/REPO.git \
~/projects/repo-work
# 自分が確認・反映する場所
git clone https://github.com/ORG/REPO.git \
~/projects/repo-publish
フォークや別のGitHubリポジトリは必要ありません。
両方とも、同じGitHubリポジトリを origin として参照します。
2. 反映用から作業用を参照できるようにする
反映用クローンに、作業用クローンを work というリモート名で登録します。
git -C ~/projects/repo-publish remote add work \
"$HOME/projects/repo-work"
Gitは、GitHubなどのURLだけでなく、ローカルディレクトリのリポジトリもfetch元として扱えます。
設定を確認します。
git -C ~/projects/repo-publish remote -v
表示例:
origin https://github.com/ORG/REPO.git (fetch)
origin https://github.com/ORG/REPO.git (push)
work /home/yourname/projects/repo-work (fetch)
work /home/yourname/projects/repo-work (push)
この構成では、次のように使い分けます。
| リモート | 接続先 | この運用での用途 |
|---|---|---|
origin |
GitHub | fetchとpush |
work |
作業用クローン | fetchのみ |
remote -v には work のpush先も表示されますが、この運用では work へpushする必要はありません。
3. 作業用でClaude Codeに変更してもらう
まず作業用の develop を最新化します。
cd ~/projects/repo-work
git status
git switch develop
git pull --ff-only origin develop
git status で作業中の変更がないことを確認してから進めます。
ここからClaude Codeに編集・変更をしてもらいます。私の運用では、例えば次の方針を伝えています。
このディレクトリは作業用クローンです。
- 編集とローカルコミットを行ってください
- GitHubへのpushは行わないでください
- 反映用クローンは変更しないでください
- コミット前に変更内容とテスト結果を確認してください
作業結果を確認し、ローカルコミットを作成します。
git status
git diff
git add src/example.py tests/test_example.py
git commit -m "Fix example behavior"
ファイル名は例です。実際に反映したいファイルを指定します。
複数コミットに分けても構いません。ここではGitHubへのpushは行いません。
修正用ブランチは必須ではない
この記事では、作業用の既存 develop へ直接コミットしています。
修正内容を独立させたい場合は、作業用で次のようにブランチを作っても構いません。
git switch -c feature/fix-example
その場合、後述の取り込み元を work/develop から work/feature/fix-example へ変更します。mergeは、指定したブランチの履歴を現在のブランチへ統合する操作です。
4. 反映用で作業結果を取得する
ここからは自分が反映用ディレクトリで操作します。
cd ~/projects/repo-publish
git status
git switch develop
# GitHub側の最新状態へ更新
git pull --ff-only origin develop
# 作業用クローンの履歴を取得
git fetch work
git fetch work は、作業用のコミットなどを取得し、work/develop のようなリモート追跡ブランチを更新します。この段階では、反映用の develop や作業ファイルには変更を取り込みません。
ここが、この運用の確認ポイントです。
fetch:変更を取得する
↓
人間が差分を確認する
↓
merge:確認した変更を取り込む
5. 取り込む前に差分を確認する
未取り込みのコミットを確認
git log --oneline develop..work/develop
develop にはなく、work/develop にあるコミットを確認します。
変更ファイルと具体的な差分を確認
# ファイルごとの変更量
git diff --stat develop work/develop
# 具体的な差分
git diff develop work/develop
この2つは、両ブランチの先端の内容を比較します。作業用だけが先へ進んでいる通常の状態では、これから取り込む変更の確認に使えます。
一方、両方の履歴が分岐している場合、「先端同士の差分」と「mergeしたときに入る変更」は必ずしも一致しません。分岐していれば、その理由も確認してから進めます。
fetch前に作業用を直接確認することもできる
同じPC上にあるため、作業用を直接指定して確認することもできます。
git -C ~/projects/repo-work log --oneline -n 10 develop
git -C ~/projects/repo-work show develop
git -C は、指定したディレクトリでGitコマンドを実行するオプションです。
6. 問題なければ取り込む
git merge --ff-only work/develop
--ff-only は、早送りできる場合だけブランチを更新する指定です。マージコミットを作らず、履歴が分岐している場合は停止します。
例えば、取り込み前が次の状態なら、
A──B──C──D
↑ ↑
develop work/develop
取り込み後はこうなります。
A──B──C──D
↑
develop・work/develop
作業用のコミットをそのまま反映用へ受け渡せます。
取り込んだ内容をテストし、GitHubへ送る前にもう一度確認します。
git status
# GitHubへ送る予定のコミット
git log --oneline origin/develop..HEAD
# GitHubの取得済み状態との差分
git diff origin/develop..HEAD
# 必要なテストを実行
7. 反映用からGitHubへpushする
確認できたら、反映用からだけpushします。
git push origin develop
これで、作業用で作成した変更がGitHubへ反映されます。pushは、ローカルのコミットを使って送信先のブランチを更新する操作です。
fetchとpullを使い分ける理由
この運用では、反映用で次の2段階に分けていることが重要です。
git fetch work
# ここで差分確認
git merge --ff-only work/develop
まとめて実行するなら、次のようにも書けます。
git pull --ff-only work develop
ただしpullは、取得に続いて現在のブランチへの取り込みまで行います。取得と取り込みの間に自分の確認を挟みたいので、私はfetchとmergeを分けています。
| コマンド | 役割 |
|---|---|
fetch |
相手の履歴を取得する |
merge |
取得した履歴を現在のブランチへ取り込む |
pull |
取得と取り込みを続けて行う |
push |
ローカルの履歴を送信先へ反映する |
fetch・merge・pushは別々の段階なので、「取得しただけ」「ローカルへ取り込んだ」「GitHubへ送った」を区別できます。
GitHub側でも変更が進んでいた場合
自分の作業中に他のメンバーがGitHubの develop を更新すると、履歴が分岐することがあります。
A──B──C ← GitHub側のdevelop
\
D──E ← 作業用のdevelop
この場合、反映用での次の操作は停止します。
git merge --ff-only work/develop
これは異常ではなく、「単純な早送りでは統合できない」という確認のための停止です。
対応例として、作業用でGitHub側の変更を通常のmergeで統合します。
cd ~/projects/repo-work
git switch develop
git fetch origin
git merge origin/develop
# 競合があれば修正し、コミット・テストする
通常のmergeは、両方の履歴をつないで統合します。競合した場合は解消が必要です。
その後、反映用で再取得します。
cd ~/projects/repo-publish
git fetch work
# 更新後の差分を確認
git log --oneline develop..work/develop
git diff develop work/develop
git merge --ff-only work/develop
反映用でも独自コミットを作っている場合は、さらに別の分岐が生じる可能性があります。反映用は原則として確認・取り込み・pushに使い、追加修正が必要なら作業用へ戻す、というルールにすると役割を保ちやすくなります。
直接pushを禁止しているチームではPRを使う
Organizationのルールで develop への直接pushが禁止されている場合は、反映用でレビュー用ブランチを作ります。
cd ~/projects/repo-publish
git fetch origin
git fetch work
git switch --no-track -c review/fix-example origin/develop
git merge --ff-only work/develop
# 差分確認・テスト後
git push -u origin review/fix-example
GitHubで、次のPull requestを作成します。
base: develop
compare: review/fix-example
この場合も、「作業用ではpushせず、反映用で確認してからGitHubへ送る」という役割分担は変わりません。
なお、PRをsquash mergeやrebase mergeすると、作業用とは異なるコミット履歴になります。以降の同期で --ff-only が通らなくなる可能性があるため、PRの取り込み方法もチームの運用に合わせてください。通常のmergeとsquashでは、履歴のつながり方が異なります。
作業用からの誤pushを防ぐ
「作業用からpushしない」というルールに加え、通常のpushを止める pre-push フックを置くこともできます。
既存のフックがないことを確認してから、次のように作成します。
cat > ~/projects/repo-work/.git/hooks/pre-push <<'EOF'
#!/bin/sh
echo "このクローンからのpushは禁止です。" >&2
echo "反映用クローンで確認してからpushしてください。" >&2
exit 1
EOF
chmod +x ~/projects/repo-work/.git/hooks/pre-push
push前の検査を失敗させることで、通常のpushを停止させる方法です。ただし、git push --no-verify では pre-push フックを回避できます。
既存のフックがある場合や、core.hooksPath で別のフック配置先を使っている場合は、その設定に合わせて組み込んでください。
注意:2クローンはセキュリティ境界ではない
この構成は、人間の確認工程を設けるためのものです。
同じOSユーザーでClaude Codeを実行しており、両方のディレクトリやGitHub認証情報へアクセスできるなら、ディレクトリを分けるだけでは操作を強制的に制限できません。
- Claude Codeへの「pushしない」という指示は、権限の剥奪とは別
- Gitフックは、回避できる誤操作防止策
- 反映用ディレクトリを分けても、OSのアクセス権が同じならアクセス可能な場合がある
強い制限が必要なら、作業環境の認証情報・OS権限・実行環境まで分離する設計が別途必要です。
また、企業のプライベートコードをAIツールで扱う可否は、このGit運用とは別の話です。会社の利用規程や契約条件に従ったうえで運用してください。
日常的に使うコマンドまとめ
作業用
cd ~/projects/repo-work
git switch develop
git pull --ff-only origin develop
# Claude Codeによる編集・確認
git add src/example.py tests/test_example.py
git commit -m "Fix example behavior"
# pushはしない
反映用
cd ~/projects/repo-publish
git switch develop
git pull --ff-only origin develop
git fetch work
# 人間が確認
git log --oneline develop..work/develop
git diff develop work/develop
# 確認してから取り込む
git merge --ff-only work/develop
# テスト後に確認してpush
git log --oneline origin/develop..HEAD
git diff origin/develop..HEAD
git push origin develop
おわりに
この運用で気に入っているのは、Claude Codeに作業を任せることと、その結果をGitHubへ反映することを、別の行動として扱える点です。
作業用では編集とローカルコミットを進め、反映用では自分が確認してから共有する。Gitの既存機能だけで、この確認の区切りを作れます。
AIによる開発支援を取り入れながら、共有リポジトリへ変更を送る判断は自分で行いたい。そんな開発スタイルの、一つの運用例になれば幸いです。