Gitの使い方|ローカルで変更・差分・コミットを練習する
※本記事にはPRを含む場合があります。
こんにちは。『脱会社員』脱サラを応援し続けるブログ、運営者の『なかびー』です。
Gitを使い始めたとき、「ファイルを保存したのに変更が残る」「addした後の修正がコミットに入らない」「間違えたので戻したいけれど、何が消えるか分からない」と戸惑うことがあります。まず整理したいのは、作業中のファイル、次に記録する内容、既に記録した履歴の三つです。
この記事では、自分のPC内に新しい練習用リポジトリを作り、架空の紅茶メモを編集します。status・diff・add・commit・logを順に使い、ステージ後の追加編集を見分け、本文を残したままステージを解除し、修正の経緯を四つのコミットで確認します。GitHubへの登録や送信は必要ありません。既存の仕事用リポジトリを操作せず、ローカルの小さな練習だけで一巡できます。
確認日は2026年10月4日です。掲載する状態遷移はLinux・Git 2.52.0で実行しました。WindowsやmacOSのターミナル画面、GUIアプリ、外部サービスとの認証やpushは未検証です。Gitの基本コマンドは共通でも、ファイルの作り方、引用符、改行、既存設定によって表示が変わるため、自分の環境ではgit –versionと各操作の結果を確認してください。
Gitの三つの状態を、作業・ステージ・コミットで分ける

ファイルの保存とコミットは別の記録
エディターで保存する操作は、作業中のファイルをディスクへ書き込むことです。Gitのコミットは、選んだ内容を履歴の一つの状態として記録することです。ファイルを保存しただけでは、その変更がGitの履歴に残ったとは限りません。逆にコミットした後でファイルを編集すれば、履歴にある内容と作業中の内容は異なります。
通常のローカル作業では、作業ツリー、ステージ、リポジトリの履歴を分けて考えます。作業ツリーは今編集しているファイル群、ステージは次のコミットへ入れる内容を用意する場所です。ステージはindexとも呼ばれます。コミットは、その時点でステージに用意された内容をもとに履歴を作ります。この記事はファイル名を指定してaddし、内容を確認してからcommitする方法に絞ります。
Gitはファイル名の一覧だけを覚えているわけではありません。addした時点の内容をステージへ反映するので、addした後に同じファイルをさらに編集すると、ステージと作業ツリーが違う状態になります。「このファイルはもう選んだから、後の変更も全部入る」と思うと、コミット漏れを起こしやすくなります。後半の練習で、この差を実際に作って確かめます。
※表は横にスクロールできます。
| 状態 | 何が入っているか | 主に使う確認 | 今回の役割 |
|---|---|---|---|
| 作業ツリー | 現在保存されているファイル | エディター・git diff | 紅茶メモを編集する |
| ステージ・index | 次に記録する予定の内容 | git diff –cached | 意図した変更を選ぶ |
| コミット | 記録済みの状態と説明 | git log・git show | 変更の経緯を追う |
| 未追跡ファイル | まだGitが追跡していないファイル | git status | 追加するか除外するか判断する |
GitとGitHubの役割を混ぜない
Gitは変更履歴を管理する仕組みで、GitHubはGitのリポジトリを共有したり、レビューしたりするサービスの一つです。この記事のinit、add、commit、logは、外部サービスのアカウントがなくてもローカルで練習できます。commitしたから自動的にインターネットへ公開されるわけではありません。
ただし、ローカルだから秘密を履歴に入れてよい、という考え方も避けましょう。後で共有先を設定して送信する可能性があるほか、フォルダー自体をバックアップ・共有する場合もあります。いったんコミットした情報は、現在のファイルから消しても古い履歴に残る場合があります。最初から秘密情報を含めない練習データを使い、何が追跡されるか確認します。
共同作業で使うclone、fetch、pull、push、プルリクエストなどは、ローカルの状態を理解した後の段階です。今回の完成条件には含めません。接続先や公開範囲を決めずに送信コマンドを試す必要はありません。まず手元で「何をコミットしたか」を説明できるようになると、その後の共有時にも確認すべき内容が明確になります。
statusとdiffで、状態と内容を別々に見る
git statusは、追跡しているファイルに変更があるか、ステージ済みか、未追跡があるかを確認する入口です。git diffは、通常、作業ツリーとステージの差を表示します。git diff –cachedはステージと現在のコミットの差を表示します。二つのdiffは、同じファイルでも違う比較をしている点が重要です。
何も表示されないdiffだけを見て「変更はない」と判断しないでください。変更が既にステージされていれば通常のdiffには出ず、–cached側に出ます。新しい未追跡ファイルも、通常のdiffには内容が表示されません。statusで状態を見てから、目的に合うdiffを選ぶ順番にすると、空の表示を誤解しにくくなります。
公式のgit statusとgit diffには比較対象と表示形式が説明されています。最初から短縮表示を暗記するより、長いstatusの説明と実際のファイル内容を照合し、慣れてきたら–shortで簡潔に確認するとよいでしょう。
コマンドは一行ずつ、現在地を確かめて進める
同じコマンドでも、どのフォルダーで実行するかによって対象が変わります。練習中は、ターミナルの現在地とGitリポジトリの最上位を確認してから操作します。特にaddやcommitは、仕事用のフォルダーで誤実行しないよう注意します。一度に長いコマンド列を貼り付けず、結果を読んでから次へ進めてください。
この記事のコマンド中の–は、後ろをファイル名などのパスとして区切るためのものです。README.mdのような単純な名前でも付ける形に統一しています。画面に表示される$やPS>などのプロンプトは、入力するコマンドに含めません。引用符は半角のものを使い、文章用の曲がった引用符へ置き換えないようにします。
新しい練習用リポジトリと、最初のコミットを作る

新しい空のフォルダーを選ぶ
Gitが使えるターミナルでgit –versionを実行します。見つからない場合は、OSに合うGit公式の導入案内を確認してください。組織管理PCでは導入方法を管理者に確認します。この記事の例はGit 2.28以降で利用できるinit -bを使い、初期ブランチ名をmainに指定します。古い版で未対応なら、既存設定を無理に変更せず対応する公式手順を確認してください。
ファイル管理アプリで、既存リポジトリの外にgit-lessonという新しい空のフォルダーを作り、その中でターミナルを開きます。既に同名のフォルダーがある場合は別名にします。ホームフォルダー全体や仕事の資料置き場でgit initを実行せず、練習専用の狭い範囲だけを管理対象にします。
git --version
git init -b main
git rev-parse --show-toplevel
git status
rev-parseの出力が、今作った練習フォルダーであることを確認します。initによって通常は.gitという管理用ディレクトリができます。ファイル管理アプリで隠し項目が見えなくても、statusが利用できれば作成を確認できます。.gitの中身を手で編集したり、初期化のやり直しとして削除したりする必要はありません。
架空のメモと除外ルールを用意する
練習フォルダーの直下にREADME.mdを作り、次の内容をUTF-8のテキストとして保存します。紅茶を入れる架空のメモであり、実際のおすすめレシピを示すものではありません。Gitの差分を分かりやすくするため、短い英語の行を使っています。行末に不要な空白を入れず、最後にも改行を一つ入れます。
# Tea memo
Duration: 3 minutes
Water: 200 ml
同じ場所に.gitignoreを作り、次の内容を保存します。.gitignore.txtになっていないか、拡張子を表示して確認してください。今回は.envと.envで始まる設定ファイルを通常の追加対象から除外し、公開用の例である.env.exampleだけを例外にします。.venv/はPythonの仮想環境を入れないための例です。
.env
.env.*
!.env.example
.venv/
さらに.env.exampleにDEMO_LABEL=sampleの一行を、.envにDEMO_LABEL=local-practiceの一行を保存します。どちらも秘密情報ではない架空のラベルです。本物のパスワード、APIキー、アクセストークンは使わないでください。除外が働くかを見るための無害な二つのファイルです。
追加前と追加後の違いを見る
まずstatusを確認します。標準的な設定ではREADME.md、.gitignore、.env.exampleが未追跡として見え、.envは通常の一覧には出ません。.envが見える場合は、除外ファイルの名前と保存場所を見直してください。git check-ignore -v — .envを使うと、どの除外ルールが適用されているか調べられます。
git status --short
git check-ignore -v -- .env
git diff -- README.md
git add -- README.md .gitignore .env.example
git status
git diff --cached
add前のREADME.mdは未追跡なので、通常のdiffに内容が出ないことがあります。add後は–cachedの差分に、新しいファイルの行が追加として表示されます。ここで、.env.exampleが本当に架空のラベルだけであること、.envを選んでいないこと、READMEの数値が3分・200mlであることを確認します。
最初のコミット前には、比較元となるコミットがまだありません。この段階の–cachedはステージにある新規内容を表示できますが、後述するrestore –stagedによる解除は、この記事では最初のコミットを作った後の練習として扱います。前提が違う場面で同じ操作を使わないよう、手順の順番を守ってください。
練習用の著者情報でコミットする
コミットには著者の名前とメールアドレスが記録されます。外部サービスへログインする認証情報ではありませんが、後から履歴を共有すると見える情報です。今回は実在の個人情報を使わず、Practice Authorとpractice@example.invalidという練習用の架空値を、このコマンドだけに指定します。–globalでPC全体の設定を変える必要はありません。
git -c user.name="Practice Author" -c user.email="practice@example.invalid" commit -m "Add initial tea memo"
git status
git log --oneline -1
-cの指定は今回のGit呼出しに対する設定です。以後のコミットでも同じ形を使います。実務ではチームの方針やサービスのプライバシー用アドレスなどに従い、記録する名前・アドレスを決めてください。架空値を仕事の履歴へそのまま使う例ではありません。
コミット後、追跡対象に未記録の変更がなければ、statusは作業ツリーがきれいな状態を示します。logには短いコミットIDとメッセージが表示されます。IDは時刻や内容などで変わるので、この記事と同じ文字列になる必要はありません。メッセージと、READMEの記録内容が一致していることを確認します。
編集後の差分とステージ後の追記を見分ける

まず時間だけを変えてステージする
README.mdのDurationを3 minutesから4 minutesへ変更し、保存します。Waterは200 mlのままです。git statusでREADMEの変更を確認し、git diff — README.mdで、3から4への変更だけが表示されることを見ます。差分の先頭にある+や-はGitの表示記号なので、ファイルへ書き込まれている文字ではありません。
git status --short
git diff -- README.md
git add -- README.md
git diff --cached -- README.md
通常の差分では、削除側にDuration: 3 minutes、追加側にDuration: 4 minutesが出ます。addすると、この4分への変更がステージへ反映されます。この時点でgit diff — README.mdが空でも正常です。作業ツリーとステージが同じ内容になったためで、履歴に記録済みという意味ではありません。–cachedには、まだ最初のコミットとの差が残っています。
ステージを「付箋で選んだファイル」とだけ覚えるより、「次に記録する内容を準備した」と考えると、次の操作の意味が分かりやすくなります。ファイルの一部だけを選ぶ高度な方法もありますが、今回はREADME全体のその時点の内容をステージする例です。
addした後で水量を変える
次に、コミットせずにREADME.mdのWaterを200 mlから250 mlへ変え、保存します。Durationは4 minutesのままです。ここでは、まだもう一度addしないでください。作業ツリーは4分・250ml、ステージは4分・200ml、最初のコミットは3分・200mlという三つの異なる状態になります。
git status --short
git diff -- README.md
git diff --cached -- README.md
この条件では、短縮statusのREADME.mdの前にMMが表示されます。左のMはコミットに対するステージの変更、右のMはステージに対する作業ツリーの変更を示します。通常のdiffには水量200から250への差、–cachedには時間3から4への差が出ます。一つのファイルに二種類の差があることを、数値で確かめてください。
※表は横にスクロールできます。
| この時点の場所 | Duration | Water | 何と比較するか |
|---|---|---|---|
| 最初のコミット | 3 minutes | 200 ml | git show HEAD:README.mdで記録を見る |
| ステージ | 4 minutes | 200 ml | –cachedでコミットとの差を見る |
| 作業ツリー | 4 minutes | 250 ml | 通常のdiffでステージとの差を見る |
| 次に通常のcommitをした場合 | 4 minutes | 200 ml | 水量の追記はまだ含まれない |
ここで普通にcommitすると、今回の手順ではステージの4分・200mlが記録され、水量の追記は作業ツリーに残ります。最新ファイルの全部が自動的に入ると思い込まないようにしましょう。この記事では、そのままコミットせず、次の章でステージをいったん解除し、二つの変更を確認し直してからまとめて記録します。
statusの二文字と空白を読む
短縮statusは二つの位置で状態を表すため、空白にも意味があります。既に追跡されているREADMEなら、先頭が空白で次がMの「 M」は作業ツリーだけの変更、Mの後が空白の「M 」はステージ済みの変更を示します。MMは両方に差がある状態です。未追跡の??は別扱いで、まだ履歴管理に含める選択をしていないファイルです。
表示の空白を文章から見分けにくい場合は、git statusの長い説明を使ってください。色だけで判断しないことも大切です。ターミナルの配色や設定によって色の意味が見えづらい場合があります。ファイル名、分類、実際のdiffを組み合わせれば、色に頼らず状況を確認できます。
削除、名前変更、競合などでは別の記号も出ます。知らない記号が出たら、今回の単純なMの例へ無理に当てはめず、statusの説明と公式資料を確認します。特に競合中は、二文字の意味が通常時と異なるため、状態の表示だけを見て機械的にaddしないようにしましょう。
コミット直前はステージ側を読む
編集直後のファイルを目視していても、ステージ側に古い内容が残っていれば、そのまま記録される場合があります。コミット直前にはgit diff –cachedを読む習慣を付けます。複数ファイルの作業でも、何を追加したか、余計なファイルが混ざっていないか、説明メッセージと変更が対応しているかを確認できます。
最初の練習ではgit add .やgit commit -aのように広い範囲をまとめる操作を使わず、対象名を明記します。広い操作が常に悪いわけではありませんが、対象を理解する前に使うと、ローカル設定や作業途中の変更まで含める原因になります。まず一つのファイルで、どの内容がどの場所へ移るかを確認してから範囲を広げてください。
本文を残してステージを解除し、修正を履歴へ残す

取り消したいものが「選択」か「本文」かを決める
「戻す」という言葉には、次のコミットへ入れる選択を外す、ファイルの編集を捨てる、記録済みの変更を打ち消す、履歴そのものを書き換える、という複数の意味があります。対象を決めずにネット上のコマンドを試すと、必要な変更を失う可能性があります。まずstatusと二種類のdiffを読み、どの状態をどうしたいか言葉にします。
今回はREADMEの4分・250mlという本文を残し、ステージだけを最初のコミットの状態へ戻します。最初のコミットが既に存在するという前提で、次を実行します。–stagedが付いていることを確認してください。この指定では作業ツリーの本文を復元対象にしません。
git restore --staged -- README.md
git status --short
git diff --cached -- README.md
git diff -- README.md
実行後、–cached側のREADME差分は空になり、通常のdiffには時間3から4、水量200から250の両方が出ます。エディターでREADMEを開くと4分・250mlのままです。短縮statusは「 M README.md」になります。これが、本文を消さずに選択を解除できた目印です。今回のLinux検証でも、実行前後のファイル内容が同じであることを確認しました。
オプションを省いたrestoreとは区別する
git restoreは指定によって対象が変わります。–stagedを付けない通常の使い方では、作業ツリーの内容をステージなどの復元元に合わせ、未コミットの編集を失う可能性があります。この記事では、その操作を実行する練習はしません。選択解除のつもりでオプションを落とさないでください。
強制的なresetやcleanも、初心者の「よく分からないので元へ戻す」ための万能手段として使わない方が安全です。Gitが追跡していないファイルや、まだコミットしていない変更は、期待する形で復元できない場合があります。大切な変更があるときは、まず別の安全な場所へファイルの内容を確保し、状況を確認できる人へ相談します。
※表は横にスクロールできます。
| 戻したい対象 | 今回の対応 | 残るもの・注意点 |
|---|---|---|
| 次のコミットへの選択 | restore –stagedで対象ファイルを解除 | 作業ツリーの本文は残る。最初のコミット後の例 |
| 未コミットの本文そのもの | この記事では破棄操作をしない | 復元元と失う差分を確認するまで実行しない |
| 記録済みの誤った文言 | 正しい内容に編集し、新しいコミットを追加 | 誤りと修正の経緯が両方残る |
| 共有済みの履歴 | チームの手順で対応する | 独断の履歴書換えや強制送信を避ける |
二つの変更を確認して二番目のコミットへ
本文を残したままステージを解除できたら、改めてREADMEをaddします。–cachedで時間と水量の両方が変わることを確認してから、二番目のコミットを作ります。今回のメッセージは、時間と水量を調整したという意味です。変更内容を説明できる短い文にすると、logから後で探しやすくなります。
git add -- README.md
git diff --cached -- README.md
git -c user.name="Practice Author" -c user.email="practice@example.invalid" commit -m "Adjust duration and water"
git status
git log --oneline -2
この後、作業ツリーとステージに未記録の変更がなければ、statusはきれいな状態になります。二つのコミットがあり、最新のREADMEは4分・250mlです。変更が残っているときは、どのファイルがどの分類に出ているかを読みます。きれいにしたいからといって、残った変更を理由なく削除しないでください。
コミットを小さく分ける基準は、単に行数を少なくすることではありません。同じ目的の変更をまとめ、説明と差分が対応する単位にします。例えば誤字修正と機能追加が混ざっている場合、後からどちらかを確認しにくくなります。今回の二行は一つのメモの調整なのでまとめていますが、作業の目的に応じて単位を決めましょう。
誤った記録は修正コミットで経緯を残す
次は練習として、READMEの4 minutesを40 minutesへ変えて保存します。水量は250 mlのままです。内容を意識して記録し、その後4 minutesへ直して新しいコミットを追加します。実際の間違いを作業中に見つけた場合は、コミット前に直して構いません。ここでは履歴を読む練習のため、意図的な架空の誤記を使います。
git add -- README.md
git diff --cached -- README.md
git -c user.name="Practice Author" -c user.email="practice@example.invalid" commit -m "Record trial duration"
このコミットの後でREADMEの40 minutesを4 minutesへ戻して保存し、次を実行します。ファイルを直す操作と、修正後を記録する操作を分けて見てください。過去のコミットを消して「間違いがなかったこと」にするのではなく、どんな修正をしたかを新しく残します。
git add -- README.md
git diff --cached -- README.md
git -c user.name="Practice Author" -c user.email="practice@example.invalid" commit -m "Correct trial duration"
git log --oneline --reverse
git show HEAD:README.md
git show HEAD~1:README.md
git show HEAD~3:README.md
git status
今回の直線的な履歴では、HEADは最新、HEAD~1は一つ前の親、HEAD~3は三つ前の親をたどったコミットです。最新は4分・250ml、一つ前は40分・250ml、三つ前の最初は3分・200mlと確認できます。git showはここでは内容を表示するだけで、作業ファイルを書き換えません。マージを含む複雑な履歴では「何個前」という見方だけで判断せず、親子関係を確認します。
履歴と除外ルールを点検し、安全に引き継ぐ

四つのコミットと最終ファイルを照合する
完成時には、最初のメモ、時間と水量の調整、40分という試行の記録、4分への修正という四つのコミットがあります。最後のファイルだけ見れば4分・250mlですが、logとshowを組み合わせれば、どの順で変わったかを追えます。コミットIDを暗記する必要はなく、メッセージと差分がつながっていることを確認します。
※表は横にスクロールできます。
| 順番 | コミットの説明 | 記録されたDuration | 記録されたWater |
|---|---|---|---|
| 1 | Add initial tea memo | 3 minutes | 200 ml |
| 2 | Adjust duration and water | 4 minutes | 250 ml |
| 3 | Record trial duration | 40 minutes | 250 ml |
| 4 | Correct trial duration | 4 minutes | 250 ml |
実行検証ではコミット数4、追跡ファイルが.env.example・.gitignore・README.mdの3個、最終statusに未記録の差分がないことを確認しました。リモートは設定しておらず、外部への送信も行っていません。読者の実行ではコミットID、日時、メッセージの表示順などを自分の条件で確認してください。
statusがきれいという表示は、追跡対象の作業ツリーとステージに通常の未記録変更がないという意味です。除外された.envの中身まで安全である、秘密が過去の履歴に入っていない、外部へ共有してもよい、という保証ではありません。完成確認は状態だけで終えず、追跡されるファイルと履歴の内容も点検します。
.gitignoreは秘密情報を消す機能ではない
.gitignoreは、通常の未追跡ファイルを追加対象から除くためのルールです。既に追跡されているファイルへ後からルールを追加しても、自動的に履歴から消えるわけではありません。また、強制的に追加する指定などで追跡される場合もあります。機密保護を.gitignoreだけに任せないでください。
今回の.envは最初から未追跡の状態で除外しています。.env.exampleには必要な項目の例だけを置き、本物の値は書きません。実務で.env.exampleを用意するときも、実際の設定ファイルをコピーして値の消し忘れがないか確認します。空のダミー値や用途を説明する文字列で十分な場合は、それを使う方が安全です。
もし本物のトークンやパスワードをコミット・共有してしまった場合、現在のファイルを削除して修正コミットを作るだけでは、過去から取得される可能性が残ります。まず対象サービスの正規手順で秘密の失効・再発行を行い、必要な関係者へ連絡し、履歴や配布済みコピーの扱いを相談します。履歴の削除だけで漏えいが解決すると考えないでください。本記事では資格情報の変更や履歴の強制書換えは扱いません。
除外ルールの細部はgitignore公式資料で確認できます。!による例外、ディレクトリ単位の除外、ルールを置く場所の影響などがあるため、思い通りにならない場合はcheck-ignoreとstatusで実際の適用を調べます。例外のあるルールでcheck-ignore -vが出力したというだけで、単純に「無視されている」と断定せず、ルールが否定指定かも読み取ってください。
エラー時に全体設定を変える前に確認する
「not a git repository」と出たら、現在地が練習用フォルダーかを確認します。「Author identity unknown」と出たら、今回のcommitに-cの著者指定が含まれているかを見ます。何もコミットされない場合は、変更が未保存なのか、まだaddしていないのか、既に記録済みなのかをstatusとdiffで確認します。症状ごとに原因を分けると、必要のない設定変更を減らせます。
既存のGit設定によって、署名、フック、改行変換などの動作が追加されている場合があります。会社やチームの方針で設定されているものを、練習のために無効化しないでください。エラー文と設定の出所を確認し、管理者や教材の指定手順へ相談します。所有者が違うリポジトリへの警告なども、理由を確かめず広い例外設定を追加するのは避けます。
改行コードの違いでファイル全体が変わったように表示される場合もあります。内容変更なのか、改行・文字コードの変換なのかを切り分けてから記録します。この記事のテストはLinuxのLF改行ですが、Windowsのエディターや設定では表示が異なる場合があります。チームで改行方針が決まっているなら、それに合わせ、PC全体の設定を思い付きで切り替えないようにします。
次の作業者へ「どこまで確認したか」を渡す
引き継ぎでは、使ったGitの版、作業フォルダーの構成、追跡対象、除外方針、最新コミットの意味、再現手順をまとめます。相手がファイルだけを見るのか、履歴も含めて受け取るのかによって、必要な共有方法は変わります。リポジトリを外部サービスへ送る場合は、送信先、公開範囲、著者情報、秘密情報の有無を別途確認してから進めます。
小さな作品でも、変更の目的を説明するコミットと、使い方のREADMEがあると、後から見直しやすくなります。作品紹介へつなげる場合はプログラミングのポートフォリオの作り方で、目的・動作条件・自分の担当範囲の伝え方も確認できます。共同作業やレビューを学びたいときは、質問対応や実習範囲を整理したうえで副業向けプログラミングスクールの比較も参考にしてください。
今回実行したのは、新規ローカルリポジトリの初期化、無害なファイルの除外確認、三つの状態の差分、本文を残すステージ解除、四つのコミット、過去内容の参照です。既存リポジトリの修復、競合解決、リモート操作、認証情報の管理は別の確認が必要です。練習でできた範囲を明確にしておくと、仕事の環境へ移るときにも無理な操作を避けられます。
Gitの基本は、変更を記録する前に内容を選び、記録した後も根拠をたどれるようにすることです。statusで場所を見分け、diffで内容を読み、addの後にも確認する。この順番を一つのメモで繰り返せば、「戻したら何が消えるか分からない」という不安を減らしながら、次の実習へ進めます。
参照資料は、git add、git commit、git restore、git log、git initの公式マニュアルです。最新版の説明と、この記事で実行したGit 2.52.0の範囲を分けて確認してください。