0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeのgit操作が何をしているか分かれば、AIとのチーム開発はもっとうまくいく

0
Last updated at Posted at 2026-03-16

Claude Codeのgit操作が何をしているか分かれば、AIとのチーム開発はもっとうまくいく

はじめに: Claude Codeはgitを「使いこなしている」

Claude Codeを使っていると、コードの変更だけでなく、gitの操作まで自動でやってくれることに気づきます。

  • ブランチを切る
  • こまめにcommitする
  • pushしてリモートに同期する

私の場合はPRを作るのも面倒なので、gh CLIを使えるようにして、ブランチ作成からPR作成まで全部Claude Codeに任せています。便利ですよね。

でも、こんな経験はありませんか?

「Claude Codeがやってくれたけど、何が起きたのかよく分からない…」

gitの仕組みを理解していると、Claude Codeへの指示の出し方が変わります。「mainにpushして」と「featureブランチ切ってPR出して」では、裏で起きることがまったく違います。

この記事では、Claude Codeが裏側で実行しているgit操作を一つずつ分解して、仕組みから理解することを目指します。各セクションでは「本・図書館・しおり」の世界観で例えてから技術的な説明に入るので、gitに苦手意識がある方もイメージを掴みやすいはずです。

git fetchとgit pull — リモートとローカルの関係

本で例えると: fetchは「図書館の蔵書目録を確認する」操作。pullは「目録を確認して、さらに本を借りてくる」操作です。目録を見るだけなら手元の本は変わりませんよね。

fetchとpullは何が違うのか

gitには「リモートリポジトリ」と「ローカルリポジトリ」の2つの世界があります。この2つの間でデータをやり取りするのがfetchpullです。

コマンド やること ローカルのコードは変わる?
git fetch リモートの最新情報を取得するだけ ❌ 変わらない
git pull fetch + merge(取得して統合する ✅ 変わる
# fetchは「見に行くだけ」
$ git fetch origin

# pullは「見に行って、自分のコードに取り込む」
$ git pull origin main

.git/refs の中身を覗いてみよう

gitの内部では、リモートとローカルの情報は別々の場所に保存されています。

.git/refs/
├── heads/          # ← ローカルブランチ
│   ├── main
│   └── feature/add-login
└── remotes/
    └── origin/     # ← リモート追跡ブランチ
        ├── main
        └── feature/add-login
  • refs/heads/main → あなたのローカルのmainが指すコミット
  • refs/remotes/origin/main → リモートのmain最後にfetchしたときに指していたコミット

fetchrefs/remotes/origin/ を更新するだけ。refs/heads/ には触りません。

Claude Codeが「まずfetchしてからpullする」理由

Claude Codeはタスクを開始するとき、まずgit fetchを実行してリモートの状態を確認します。これは「いきなりpullしてコンフリクトが起きる」ことを避けるためです。

fetchで安全に状態を把握してから、必要に応じてpullする。この2段階の確認が、安全な操作の基本です。

図解: fetchとpullの違い

git branchとgit switch — ブランチの正体

身近なもので例えると: ブランチは本のしおりのようなもの。本(コード)はコピーされず、どのページを読んでいるかの目印を増やすだけです。switchはしおりを挟み替える操作。しおりを何枚増やしても本は重くなりませんよね。

ブランチは「ポインタ」でしかない

「ブランチ」と聞くと、コードが枝分かれしたコピーのようなイメージがあるかもしれません。しかし、gitのブランチの正体は1つのコミットを指すポインタです。

実際に中身を見てみましょう。

$ cat .git/refs/heads/main
a1b2c3d4e5f6789012345678901234567890abcd

たったこれだけ。40文字のSHA-1ハッシュが書かれているだけです。このハッシュが「このブランチはどのコミットを指しているか」を表しています。

switchはHEADの向き先を変えるだけ

git switch(旧git checkout)がやっていることは、HEADというポインタの向き先を変えることです。

# HEADの向き先を確認
$ cat .git/HEAD
ref: refs/heads/main

# ブランチを切り替える
$ git switch feature/add-login

# HEADが変わった
$ cat .git/HEAD
ref: refs/heads/feature/add-login

ファイルが切り替わるのは、HEADが指すコミットに合わせてワーキングツリーを更新するからです。

Claude Codeがfeatureブランチを切るとき

Claude Codeに「この機能を実装して」と指示すると、多くの場合こんな操作が走ります。

# 1. 新しいブランチを作成して切り替え
$ git switch -c feature/add-login

# これは内部的には2つのことが起きている:
# ① .git/refs/heads/feature/add-login を作成(現在のコミットを指す)
# ② .git/HEAD を refs/heads/feature/add-login に向ける

ブランチの作成は「新しいポインタを1つ作る」だけなので、コストはほぼゼロです。そのため、Claude Codeは気軽にブランチを作成できます。

detached HEADの正体

たまに見かける「detached HEAD」状態。これは、HEADがブランチではなくコミットを直接指している状態です。

# 通常: HEADはブランチを指す
$ cat .git/HEAD
ref: refs/heads/main

# detached HEAD: HEADがコミットを直接指す
$ cat .git/HEAD
a1b2c3d4e5f6789012345678901234567890abcd

この状態でコミットしても、どのブランチにも属さないため、後から見つけにくくなります。Claude Codeがブランチを必ず作るのは、この問題を避けるためでもあります。

図解: ブランチとHEADの関係

git commit — スナップショットの仕組み

本で例えると: commitは「本の全ページをコピー機でコピーして、スクラップノートに貼り付ける」操作です。変わったページだけメモするのではなく、その時点の全体をまるごとコピーする。後から「あのときどうだったっけ」と振り返れるのは、全ページのコピーが残っているからです。

commitは差分ではなく「スナップショット」

よくある誤解に「commitは変更の差分を保存している」というものがあります。実際には、gitのcommitはプロジェクト全体のスナップショットを保存しています。

# コミットの中身を見てみる
$ git cat-file -p HEAD
tree 9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b
parent a1b2c3d4e5f6789012345678901234567890abcd
author Developer <dev@example.com> 1710000000 +0900
committer Developer <dev@example.com> 1710000000 +0900

feat: ログイン機能を追加

.git/objectsの3層構造

gitのオブジェクトは3種類あります。

オブジェクト 役割 例え
blob ファイルの中身 写真1枚1枚
tree ディレクトリ構造 アルバムの目次
commit メタデータ(誰が・いつ・何を) アルバムの表紙
# commitオブジェクト → treeを指す
$ git cat-file -p HEAD
tree 9a8b7c6d...

# treeオブジェクト → blobやサブtreeを指す
$ git cat-file -p 9a8b7c6d
100644 blob 1234abcd...    README.md
100644 blob 5678efgh...    src/index.ts
040000 tree 9012ijkl...    src/components/

# blobオブジェクト → ファイルの中身そのもの
$ git cat-file -p 1234abcd
# Hello World
This is a sample project.

Claude Codeの「こまめなcommit」が安全な理由

Claude Codeは作業の途中でこまめにcommitします。「まだ途中なのにcommitするの?」と思うかもしれませんが、これには大きなメリットがあります。

commitはスナップショットなので、いつでもその時点に戻れます。

# もし何か問題が起きても、直前のコミットに戻れる
$ git log --oneline
d4e5f6a feat: バリデーション追加
c3d4e5f feat: フォーム実装
b2c3d4e feat: コンポーネント作成
a1b2c3d feat: 初期セットアップ

# 例えば「フォーム実装」の時点に戻したいなら
$ git reset --hard c3d4e5f

こまめなcommitは「セーブポイント」のようなものです。ゲームでこまめにセーブするのと同じ感覚ですね。

図解: gitオブジェクトの3層構造

git push — ローカルとリモートの同期

本で例えると: pushは「読書ノートを共有本棚に戻す」操作です。自分の手元にもノートは残りますが、共有本棚に置くことでチームの誰もが見られるようになります。戻すタイミングは自分で決められる。この「手動」が安全性の源です。

pushは「refsをリモートにコピーする」操作

git pushは、ローカルのブランチ(refs)が指すコミットと、そのコミットに必要なオブジェクトをリモートに送信します。

$ git push origin feature/add-login

# やっていること:
# 1. feature/add-login が指すコミット(とそこに至るオブジェクト)を送信
# 2. リモートの refs/heads/feature/add-login を更新

fast-forwardとnon-fast-forwardの違い

pushが成功するかどうかは、リモートのブランチとローカルのブランチの履歴の関係で決まります。

fast-forward(成功する):
リモートのブランチが指すコミットが、ローカルのブランチの祖先にある場合。つまり、リモートの履歴をそのまま「早送り」できる場合です。

リモート:  A → B → C
ローカル:  A → B → C → D → E
                          ↑ この分だけ追加すればOK

non-fast-forward(拒否される):
リモートとローカルで履歴が分岐している場合。

リモート:  A → B → C → F
ローカル:  A → B → C → D → E
                    ↑ ここで分岐している

Claude Codeがpushを拒否されるケース

Claude Codeがpushしようとして拒否されるのは、主に以下のケースです。

  1. 他の人が先にpushした — リモートが進んでいるため、fast-forwardできない
  2. mainブランチに直接pushしようとした — ブランチ保護ルールで拒否される
  3. force pushが必要な状況 — rebaseした後など、履歴が書き換わっている
# 拒否された場合の対処
$ git push origin feature/add-login
! [rejected]        feature/add-login -> feature/add-login (non-fast-forward)

# 対処法1: まずpullしてmergeする
$ git pull origin feature/add-login
$ git push origin feature/add-login

# 対処法2: force push(チームで合意がある場合のみ)
$ git push --force-with-lease origin feature/add-login

そのため、Claude Codeに「mainに直接pushして」と指示するよりも、「featureブランチを作ってpushして」と指示する方が安全です。

図解: pushの仕組み

図解: Claude Codeの1タスクで起きるgit操作の全体像

本で例えると: 「蔵書目録を確認 → しおりを追加 → 読み進める → コピー機でスクラップ → 共有本棚に戻す」。この一連の流れが、Claude Codeの1タスクで起きていることです。

ここまで個別のgit操作を見てきました。では、Claude Codeに**「ログイン画面のバグ直して」**と指示したとき、実際に何が起きるのか全体像を見てみましょう。

各ステップで起きていることの整理

ステップ gitコマンド 内部で起きること
① fetch git fetch origin refs/remotes/origin/を更新
② branch git switch -c fix/login-bug 新しいポインタ作成 + HEAD変更
③ 編集 (gitは関係なし) ワーキングツリーのファイルを変更
④ commit git add + git commit blob→tree→commitオブジェクト作成
⑤ push git push origin fix/login-bug ローカルのrefsとオブジェクトをリモートに送信

この流れを理解していれば、Claude Codeが何をやっているかが透明になります。

まとめ: 仕組みを知ると指示が変わる

この記事で見てきた内容を振り返ります。

  • fetch — リモートの情報を取得するだけ(安全な確認)
  • pull — fetch + merge(ローカルが変わる)
  • branch — コミットを指すポインタを作るだけ(コストほぼゼロ)
  • commit — プロジェクト全体のスナップショット(差分ではない)
  • push — ローカルのrefsとオブジェクトをリモートに送信

これらを理解していると、Claude Codeへの指示が具体的で安全なものに変わります。

❌ 曖昧な指示 ✅ 仕組みを理解した指示
「コード直して」 「featureブランチ切って修正して、pushしてPR出して」
「最新にして」 「fetchして差分確認してからpullして」
「mainにpushして」 「mainへの直pushは避けて、PRベースでマージして」

gitの仕組みは、Claude Codeを使わなくても役立つ基礎知識です。でもClaude Codeと一緒に働くとき、この知識があるとAIとの協業がもっとスムーズになります。

次回は「Claude Codeで起きがちなgit事故パターンとトラブルシュート」について解説する予定です。

関連記事

参考文献

Claude Codeの実践的な活用方法については、Zenn Book「Claude Code 実践ガイド」で詳しく解説しています。

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?