Git 操作マニュアル
このページの目次
現在の目的から読み始める。状態を確認してから、変更の記録・統合・復旧へ進む。各節は個別に参照できる。選択肢は明示しており、記事全体を順番に実行するスクリプトとしては扱わない。
コマンドは Git 2.53 で検証した。対象リポジトリのルートで Bash / Zsh のコマンドを実行する。旧版は git --version と、restore・switch・stash の表示オプションが利用可能かを確認する。例ではリモート名を origin、主ブランチを main、作業ブランチを feature とする。file.txt と path/to/file は実際のパス、COMMIT / KNOWN_GOOD はログやタグで確認したコミットに置き換える。既定ブランチが main とは限らない。出力は例であり、ハッシュや表示言語は環境によって異なる。
| 目的 | 参照先 |
|---|---|
| 変更と次のコミット内容を確認 | 差分の確認 |
| ブランチを作り変更を記録 | コミットの作成 |
| 作業を一時退避して再開 | 作業の退避 |
| ステージや変更、コミットを取り消す | 取り消し |
| 主ブランチの統合・競合解決・修正の移植 | ブランチの統合 |
| コミットの復旧・変更追跡・不具合の特定 | 履歴と復旧 |
| リモートとの差分確認・push | リモートとの共同作業 |
| 並行作業・依存取得・リリースタグ | worktree・submodule・タグ |
差分の確認:比較対象を区別する
三つの状態を区別する。HEAD は現在のコミット、インデックスは次のコミットに記録するスナップショット、作業ツリーは編集中のファイルである。add はその時点の内容をインデックスに記録する。その後の編集は自動的には反映されない。
現在のブランチと変更の概要
# ステージ済み・未ステージの状態とブランチ情報を表示する
--short は短形式、--branch はブランチと上流の情報を追加する。出力例:
## feature...origin/feature [ahead 1, behind 2]
MM file.txt
M README.md
A new.txt
?? notes.txt
| 表示 | 意味 |
|---|---|
MM | 第一列:HEAD とインデックスに差分。第二列:インデックスと作業ツリーにも差分。 |
·M | 第一列は空白。未ステージの変更がある。 |
A· | 新規ファイルをステージ済み。その後の変更はない。 |
?? | 未追跡。自動でコミットされず、通常の diff に内容は出ない。 |
表中の · は空白を見える形で示したもの。実際の出力は空白になる。ahead 1, behind 2 は、ローカルに記録された上流と比べ、現在のブランチ固有のコミットが 1 個、上流固有が 2 個あるという意味。サーバーには接続しないため、最新の状態は fetch して確認する。競合中の UU などは特別な意味を持つので、通常の二列とは区別して 競合解決 を参照する。状態形式
確認したい内容に応じて diff を選ぶ
# 作業ツリーとインデックスを比較し、未ステージの変更を確認する
編集中や add の前に使う。-- はリビジョン・オプションとパスの区切り。file.txt を省くと、追跡済みファイル全体の未ステージ差分を確認できる。
# インデックスと HEAD を比較し、このファイルのコミット予定内容を確認する
--cached と --staged は同義。上の MM ファイルでは、先ほどとは別の差分が表示される。コミット前にこちらを確認する。git diff --cached --stat は概要の確認用で、パッチの確認を代替するものではない。
パッチの一部の例:
-timeout = 10
+timeout = 30
- は比較元、+ は比較先の行。@@ は旧・新ファイルの行範囲を示す。これがコミット予定の差分なのかは、どの diff を使ったかで決まる。diff の仕様
コミットの作成:記録する内容を選ぶ
新しい作業用のブランチを作る
現在のコミットから作業を始める場合に使う。先に status で位置を確認する。既存の変更は通常そのまま残り、ブランチを作っても自動ではコミットされない。
# 現在の HEAD から feature ブランチを新規作成して切り替える
-c は新規作成。既存のブランチなら代わりに git switch feature を使う。変更が原因で切り替えを拒否されたら、コミットまたは stashしてから再試行する。
ファイル全体または変更の一部をステージする
# このファイルの現在の内容をステージする
ファイル内の変更をまとめて記録したい場合に使う。削除済みなら削除を記録する。追跡済みファイルに別の目的の変更が混在している場合は、全体を先にステージせず、次の対話操作を選ぶ:
# 今回のコミットに含める変更を差分単位で選ぶ
y で現在の差分をステージ、n で未ステージのまま、s で分割を試み、q で選択を終了する。分割できなければファイルを調整するか、e で慎重にパッチを編集する。選び間違えても ステージ解除 なら作業ファイルは失われない。未追跡の新規ファイルはまず全体をステージできる。対話的なステージ操作
確認してコミットし、結果を確かめる
# ステージ済みの差分全体を確認し、コミット範囲を確かめる
対象ファイル、パッチ、プロジェクトのテスト結果を確認してから進む。通常の git commit が記録するのはインデックスであり、その後の編集や未追跡ファイルではない。
# 確認済みのスナップショットをコミットする。メッセージは変更の目的に置き換える
# 作成したコミットと対象ファイルを確認する
# コミットされずに残っている変更を確認する
二つはコミット後の確認。部分的にステージした場合、変更が残っていても失敗とは限らない。直前の未共有コミットのメッセージだけを直すなら git commit --amend --only -m "New message" を使う。--only は別のステージ済み変更の混入を防ぐ。amend はコミットの識別子を変更する。commit と amend
作業の退避:保存・確認・復元・削除
コミットに適さない途中の作業を一時中断するときに使う。stash は現在のリポジトリ内に保存され、バックアップサービスではない。submodule 内の変更は個別に扱う。
# 追跡済みの変更と未追跡ファイルを、識別しやすい説明付きで退避する
-u は未追跡ファイルを含めるが、無視対象は含めない。成功後、git status --short で退避対象が作業ツリーから外れたことを確認してから切り替える。無視対象のファイルは残るため、ディレクトリ全体を保存したわけではない。
# 説明から復元対象を探し、先頭の項目と決めつけない
stash@{0}: On feature: before branch switch
以降は確認した stash@{0} を使う。他の stash の追加や削除で番号が変わるため、削除前には再確認する。
# 退避した未追跡ファイルも含めてパッチを確認する
復元先のブランチにいることと、status に他の未コミット作業がないことを確認してから適用する:
# 内容を復元し、確認用に stash 自体は残す
既定では元のステージ状態までは復元しない。そこも復元したい場合は、上のコマンドの代わりに git stash apply --index 'stash@{0}' を使う。復元後は status、未ステージ差分、ステージ済み差分、関連テストを確認する。競合したら再度 apply せずファイルを解決する。stash には汎用の --abort がないため、適用前に作業ツリーをクリーンにしておく。
# 復元内容と現在の項目番号を確認した後に、この stash を削除する
git stash list で削除を確認する。pop は適用と成功時の削除をまとめた操作で、競合時は通常項目が残る。ここでは apply / drop を分け、削除前に確認する。stash の仕様
取り消し:変更する対象を選ぶ
まず二種類の diff で残したい内容を確認する。次の表の各行は別々の目的であり、実行順序ではない。
| 目的 | 変更対象 | 参照先 |
|---|---|---|
| add を取り消し、ファイルは残す | インデックス | ステージ解除 |
| ファイルの未ステージ変更を破棄 | 作業ツリー | ファイルの復元 |
| 直前の未共有コミットを取り消す | 現在のブランチ参照 | ローカルコミットの取り消し |
| 共有済み変更を取り消す | 打ち消すコミットを追加 | revert |
図は毎回 HEAD が B、インデックスが C、作業ファイルが D の状態から始まり、reset の対象は以前の A である。操作を選んで変化を比較する。各操作は独立しており、結果は累積しない。 A / B / C / D は例のファイルの異なる内容を表す。
同じ初期状態から soft は HEAD、mixed は index も、hard は worktree も更新する。restore --staged は HEAD を移動しない。
作業ファイルを残してステージ解除する
# インデックスの対象を HEAD に戻し、編集中のファイルは残す
--staged はインデックスだけを対象にし、既定の復元元は HEAD。実行後の git diff --cached -- file.txt は空になり、追跡済みファイルの変更は通常の diff で確認できる。新規追加したファイルは未追跡に戻るため、通常の diff ではなく status で確認する。初回コミットが存在することを前提とする。restore の復元元と対象
未ステージ変更の破棄・過去のファイルの取得
file.txt の add 後の編集だけを捨てるなら、先に git diff -- file.txt を読み、その差分が不要なことを確認する:
# インデックスの内容で作業ファイルを上書きし、未ステージ変更を破棄する
通常の diff は空になり、ステージ済み差分は変わらない。--source を指定しない場合はインデックスから復元するため、直前のコミットに戻るとは限らない。一度もコミットしていない編集は、通常 reflog では復旧できない。
過去のコミットから一つのファイルを取得する場合は別の操作になる。先に対象の版と内容を確認する:
# 指定コミットのファイル内容を表示する。作業ツリーはまだ変更しない
# 現在の変更を保存した後、選んだ過去の内容で作業ファイルを置き換える
--source は復元元を明示する。この操作はブランチを移動せず、ステージもしない。git diff -- path/to/file で結果を確認してから add / commit する。復元元に追跡済みの対象パスがなければ、restore はその状態に合わせて削除するため、先の show で確認する。
変更を残して直前のローカルコミットを取り消す
現在のブランチの直前のコミットが未共有で、親コミットが存在する場合に使う。git show HEAD で対象を確認する。既存のステージ済み・未ステージ変更も残るので、後で合わせて確認する。先に現在のコミットへの参照を残す:
# 現在のコミットへの参照を残す。未コミットの編集は保存されない
未使用のブランチ名を選ぶ。作成に失敗したら先に解決してから soft reset に進む:
# 現在のブランチを親コミットへ戻し、インデックスと作業ファイルは保持する
HEAD~1 は第一親を一つたどったコミット。git log -1 --oneline で移動先を確認し、二種類の diff で再コミットする内容を確かめる。すべて未ステージに戻したい場合は、soft の代わりに git reset --mixed HEAD~1 を選ぶ。soft の後に同じ HEAD~1 を指定すると、さらに一つ前へ戻ってしまう。
図の hard は追跡済みの作業ファイルも上書きし、対象パスを妨げる未追跡ファイルを削除する場合がある。現在の状態を捨てるための選択肢であり、soft / mixed の後に行う仕上げではない。戻しすぎた場合は reflog による復旧 で元のコミットを特定し、参照を作る。reset の各モード
共有済みコミットの効果を取り消す
作業ツリーとインデックスをクリーンにし、git show COMMIT で打ち消す通常のコミットを確認する。revert は共有履歴を残したまま、逆の変更を行うコミットを追加する。
# 現在のブランチに、対象の変更を打ち消すコミットを作る
成功後は git show HEAD と関連テストで確認する。後続のコードが取り消した変更に依存している場合がある。競合時は編集し、git add -- file.txt で解決済みにしてから git revert --continue。中止する場合は代わりに git revert --abort を使う。merge commit の revert は、-m でどの親を基準にするかと、後の merge への影響を理解してから行う。revert の仕様
ブランチの統合:先に方法を選ぶ
作業ツリーとインデックスがクリーンな状態から始める。origin/main はローカルのリモート追跡参照なので、まず fetch して主ブランチの状態を取得する。
# リモート追跡参照を更新する。現在のブランチのファイルは変更しない
| 選択 | 結果 | 用途 |
|---|---|---|
| merge | 既存コミットを保持。fast-forward または merge commit | 別ブランチの履歴を取り込む |
| rebase | 新しい基点に再適用。通常は識別子が変わる | 未共有の作業ブランチを更新する |
| cherry-pick | 選択したコミットの変更を適用 | 依存を確認して特定の修正だけを移植する |
履歴を保つ:feature を main に統合する
ここでは main が feature を受け入れる。まず受け入れ側へ切り替える。merge の引数は取り込む側のブランチ名である。
# 変更を受け入れる main ブランチへ切り替える
# 取得済みの origin/main へ fast-forward する。分岐していれば停止する
fast-forward を拒否されたら、リモートとの差分 でローカル固有のコミットを調べる。成功してから作業ブランチを統合する:
# 現在の main に feature の履歴を取り込む
main が feature の祖先なら、既定では merge commit を作らず fast-forward できる。統合点を明示したい場合は、代わりに git merge --no-ff feature を使う。git log --graph --oneline -10 とテストで確認し、プロジェクトの手順に従って push する。merge の仕様
未共有の作業ブランチを rebase で更新する
上とは別の選択肢で、feature の基点を主ブランチに更新する。未共有の作業を対象とし、共有済み履歴を書き換える場合は利用者と調整する。
# 基点を更新する作業ブランチに切り替える
# 作業ブランチのコミットを取得済みの origin/main 上へ再適用する
成功後は git log --graph --oneline -10 とテストで確認する。競合すると一つのコミットで停止するので、次節に従って解決する。競合しなかっただけでは動作の正しさは保証されない。rebase の仕様
競合で停止した場合:解決して続行、または中止
# 停止中の操作と Git が示す次の手順を確認する
# 未解決のパスを一覧にして、順に解決する
--diff-filter=U は未マージのパス、--name-only はファイル名のみを選ぶ。両側の変更を理解して最終内容に編集し、<<<<<<<、=======、>>>>>>> などの印を取り除く。ours / theirs を単純に「自分 / 相手」と考えない。特に rebase では文脈が異なる。
# 手作業で解決したファイルを解決済みにする。実際のパスごとに行う
削除で解決する場合は add の代わりに git rm -- file.txt を使う。未解決パスがなくなったことと git diff --cached を確認し、停止中の操作に対応する続行コマンドを一つだけ選ぶ:
| 停止中の操作 | 解決後に続行 | 中止する場合 |
|---|---|---|
| merge | git merge --continue | git merge --abort |
| rebase | git rebase --continue | git rebase --abort |
| cherry-pick | git cherry-pick --continue | git cherry-pick --abort |
rebase は後のコミットでも停止することがあるため、確認と解決を繰り返す。--skip は変更を残したままエラーだけ飛ばす操作ではなく、コミットを適用しない操作である。完了後は status に進行中の操作が表示されないこととテスト結果を確認する。abort は統合の中止用であり、開始前に混在していた未コミット作業のバックアップではない。
一つの修正だけを移植する
修正を受け入れるブランチで実行する。先に git show COMMIT で元の変更と依存を確認する。次は通常の単一親コミットを対象とする。
# 選んだ修正を現在のブランチに適用し、メッセージに元のコミットを記録する
-x は保守ブランチ間で元のコミットを追跡しやすくする。git show HEAD とテストで確認し、競合を解決した場合はメッセージの出典も確認する。続行・中止は上の表を参照する。cherry-pick の仕様
履歴と復旧:現象からコミットを探す
ブランチ関係と個別の変更を確認する
# ローカルの各参照からたどれる最近の履歴とブランチ位置を確認する
--graph は接続線、--oneline は一行表示、--decorate は参照名、--all はリモート追跡参照を含むローカル refs 全体、-30 は件数制限。サーバーには問い合わせない。調べたいハッシュを見つけたら個別に開く:
# 選んだコミットの説明とパッチを読み、対象の変更か確認する
メッセージではなくコードの変化から探す
# 指定文字列の出現数を変えたコミットとパッチを探す
-S はシンボルの追加・削除時点を探すのに向く。出現数が変わらない移動は見つからない場合がある。追加・削除行を正規表現で探すなら、代わりに次を使う:
# パッチ内で timeout の代入に一致する変更行を探す
-p はパッチ表示、パスは検索範囲の限定。どちらも既定では HEAD からたどれる履歴を検索する。他のブランチも対象にするなら参照や --all を指定する。
# 現在のファイルの 40〜60 行を最後に変更したコミットを調べる
表示されたハッシュを git show で開き、変更理由を調べる。blame は行の由来を示すもので、整形だけでも最後の変更になり得る。障害の原因や責任をそのまま示すものではない。履歴検索のオプション
誤った reset やブランチ削除から復旧する
# ローカルの HEAD 移動記録から、操作前の位置を探す
出力の一部の例:
a1b2c3d HEAD@{2026-09-10 12:05:00 +0800}: reset: moving to HEAD~1
b2c3d4e HEAD@{2026-09-10 12:00:00 +0800}: commit: Fix timeout handling
この例では操作前の b2c3d4e が候補。実際のハッシュを次の COMMIT に入れる。先にパッチを確認してから参照を作る:
# 候補のコミットに失われた変更が含まれるか確認する
# 復旧用ブランチを作ってコミットを保持する。作業ツリーは変更しない
recovery は未使用の名前にする。git log -1 --oneline recovery で確認後、クリーンな作業ツリーから git switch recovery するか、別の worktree で調べる。復旧した内容を確認してから取り込み方法を決める。
reflog はローカルの記録で、期限やガベージコレクションの影響を受ける。他のマシンの移動は記録されず、すべての内容が復旧できる保証もない。固定の日数や未コミット編集の復元を当てにしない。reflog の仕様
bisect で不具合を導入したコミットを絞る
再現可能な同じ検査を用意し、HEAD で問題が起き、KNOWN_GOOD では起きないことを確認する。クリーンな状態から始める。中間版がチェックアウトされるので、ビルド生成物が判定に影響しないようにする。
# HEAD を bad、確認済みの正常な版を good として二分探索を始める
Git が中間コミットを選んだら同じ検査を実行し、実際の結果から一つ選ぶ:
| 今回の結果 | コマンド | 次の動作 |
|---|---|---|
| 問題が起きない | git bisect good | 範囲を狭めて次を選ぶ |
| 問題が起きる | git bisect bad | 範囲を狭めて次を選ぶ |
| ビルド不可・判定不能 | git bisect skip | この版を除外。最終候補が複数残ることがある |
is the first bad commit と出るまで繰り返し、ハッシュを記録して git show で確認する。安定した検査と二分探索に適した境界が前提で、間欠的な問題や導入・修正が繰り返された問題では追加検証が必要。終了時または中止時に元の位置へ戻す:
# 二分探索を終了し、開始前の位置へ戻る
git status --short --branch で元のブランチを確認する。自動化するなら手動判定の代わりに git bisect run /absolute/path/check-regression.sh を使える。終了コード 0 は good、1〜127 のうち 125 以外は bad、125 は skip。スクリプトはリポジトリ外に置き、終了コードを事前確認する。無関係なビルド失敗を今回の不具合と誤判定させない。bisect の仕様
リモートとの共同作業:進捗を比較してから push する
接続先と双方に固有のコミットを確認する
# origin の fetch・push 先が目的のリポジトリか確認する
# 更新を取得し、リモートで削除されたブランチの追跡参照を整理する
通常のブランチ refspec では、--prune は古いリモート追跡参照を削除し、ローカル作業ブランチは削除しない。タグやミラー用 refspec があれば先に範囲を確認する。取得後、現在のブランチと対応する origin/feature を比較する:
# 現在のブランチとリモート追跡ブランチに固有のコミットを表示する
< a1b2c3d Fix timeout handling
> b2c3d4e Update server defaults
三点範囲は片方だけにあるコミットを選ぶ。< は HEAD 側、> は origin/feature 側。出力なしなら固有コミットなし、両方あれば分岐している。リモートに feature がなければ初回 push なので、この比較は省く。
push 元・先と上流を明示する
次は現在の HEAD をリモートの feature に送る。git status --short --branch で目的のローカル feature にいることを確認し、事前にレビューとテストを終える。
# リモート参照を更新せず、更新先をプレビューする
コロンの左が元、右がリモートの送り先。refs/heads/ はブランチを明示する。対象が正しいことを確認してから実際に push する:
# 現在のブランチを push し、origin/feature を上流に設定する
-u は追跡関係の設定で、強制更新ではない。成功後は git branch -vv で上流を確認し、git ls-remote --heads origin refs/heads/feature のハッシュを git rev-parse HEAD と照合する。その後サーバーが更新される可能性はある。dry-run はロックでも、すべてのサーバー側検査の合格保証でもない。
拒否された場合:分岐と意図した書き換えを区別する
non-fast-forward は通常、今回の push では保持されない履歴がリモート側にあることを示す。fetch して双方を調べ、merge / rebase を選ぶ。権限、保護ブランチ、hook による拒否はサーバーの説明に従う。force では解決しない。
以下は、合意済みで意図した履歴の書き換えを反映するときだけ使う。通常の --force-with-lease は追跡参照に依存し、バックグラウンド fetch で比較基準が変わる場合がある。確認対象のコミットを変数に固定する:
# 上書き対象の状態を取得する。失敗したら停止する
# この shell に想定するリモートのコミットを記録する。失敗・空なら停止する
expected_oid=
# 置き換える履歴を確認し、双方の変更を扱えているか確かめる
ここでは実際に履歴を確認する。fetch の成功だけで上書き可能とは判断しない。確認後、同じ shell で実行する:
# リモートの feature が確認済みの想定コミットを指す場合だけ、書き換えを反映する
${expected_oid:?...} は変数が未設定・空なら展開を拒否する。lease の失敗は想定が崩れたことを示すため、変数だけ更新せず新しいリモート作業を調べる。成功後は通常の push と同様に確認する。push と明示的な lease
worktree・submodule・タグの操作
現在の編集を保ち、別ディレクトリで修正する
worktree は一時的な修正や bisect に使える。オブジェクトと多くの参照を共有し、作業ディレクトリ・HEAD・インデックスは別になる。取得済みの origin/main から新しい hotfix ブランチと隣の ../hotfix を作る。未使用の名前と新しいパスを選ぶ。
# hotfix 用の作業ディレクトリを作り、現在の編集は元の場所に残す
-b はブランチ作成、パスは作業ディレクトリ、最後は開始点。通常、同じブランチを二つの worktree に同時チェックアウトすることはできない。次で確認する:
# 各作業ディレクトリとブランチを確認する
# 元のディレクトリから hotfix の状態を確認する
-C は指定ディレクトリで Git を実行する。編集とテストは ../hotfix 内で行う。修正をコミットして統合した後、git -C ../hotfix status --short --ignored で残ったファイルを確認する。無視対象の .env などもディレクトリとともに削除されるので、必要な内容は先に移す。その後、元のディレクトリから削除する:
# 作業済みのディレクトリと登録を削除する。hotfix ブランチは残る
git worktree list で削除を確認する。変更が残っていて拒否されたら、--force を付ける前に必要な内容を保存する。ブランチは残るので、統合済みで不要なら別途 git branch -d hotfix を使う。未マージとして拒否された場合は、squash などの統合方法と受け入れ先の内容を先に確認する。worktree の仕様
親リポジトリが記録した submodule の版を取得する
.gitmodules がある親リポジトリのルートで実行する。まず記録とチェックアウト状態を確認する:
# 入れ子を含む submodule のコミットと初期化状態を確認する
行頭の - は未初期化、+ は親のインデックス記録と異なるコミット、U は競合を示す。空白はコミット一致であり、作業ツリーがクリーンという意味ではない。更新前に各対象で git -C path/to/submodule status --short を確認し、変更を保存する。
# 未初期化の submodule を取得し、親が記録したコミットをチェックアウトする
--init は初期化、--recursive は入れ子への適用、--checkout はチェックアウト方式の明示で、通常 detached HEAD になる。再度 status を確認し、未初期化やコミット不一致の印がなくなったことを確かめる。競合やローカル変更で拒否されたら原因を先に解決する。
依存の更新は別の作業。--remote は親の記録を再現せず、submodule のリモート追跡ブランチから版を選ぶ。更新内容を確認し、親プロジェクトをテストしてから、新しい submodule 参照を親でコミットする。初期化の代用にはしない。submodule の仕様
確認済みコミットにタグを付けて公開する
例では未使用の v1.0.0 を使う。git show --stat HEAD で対象を確認し、git status --short で公開内容がコミット済みか確かめる。タグはコミットを指し、作業ツリーの未コミット変更は含まない。
# 明示した HEAD に注釈付きローカルタグを作る
-a は説明と作成者情報を持つタグオブジェクトを作る。git show v1.0.0 で対象と説明を確認し、このタグだけの送信をプレビューする:
# 他のローカルタグを送らず、このタグの送り先を確認する
公開対象を確認してから実行する:
# 確認済みの一つのタグを origin へ送る
# ローカルの注釈付きタグオブジェクトのハッシュを取得する
# サーバーの同じタグオブジェクトを問い合わせ、ハッシュを照合する
ここで比べるのはタグオブジェクトのハッシュで、参照先コミットのハッシュではない。リモートに異なる同名タグがあれば公開記録を調べる。利用済みのリリースタグを安易に強制上書きしない。タグの仕様
関連資料
全オプションは git help <subcommand>(例:git help restore)で参照できる。公式マニュアルでオプションの意味を確認し、本ページの各手順で確認・選択・実行・検証をつなぐ。