
シリーズ:Git 実践シリーズ
01
ソース管理ワークフロー
02
タグの使い方(ローカル / Gitea Web)
03
コミットメッセージ規約
04
rebase の使い方
05
GitHub / Gitea Actions
チーム開発でも個人開発でも、ソースコードのバージョン管理は欠かせません。なかでも Git は事実上の標準ツールです。コマンドそのものは検索すればすぐ出てきますが、いざ実務で運用しようとすると「 どの順番で、ローカルとリモートのどちらを操作すればいいのか 」で迷いがちです。
この記事では、単発のコマンド集ではなく「実際の運用の流れ」に沿って、次の4つのワークフローを通しで身につけます。
- ローカルとリモートでのコードのやり取り(push / pull)
mainを本番相当に保ちながら、作業ブランチで機能追加・改修を進める- 開発の途中で本番への 急ぎの修正 が入ったときの対処
- 機能が完成・リリースされた後に、ブランチを
mainへ統合する
すべてのコマンドに「 ローカルでの作業か 」「 リモートに影響する作業か 」を示すバッジと注釈を付けています。いま自分がどこを操作しているのか迷わず読み進められるはずです。
ローカル
=自分のPC内だけで完結
リモート
=GitHub等のサーバーへ送受信
✨ この記事のスタンス(モダンなGit)
古い日本語記事の多くはgit checkout でブランチ操作を説明しています。本記事では Git 2.23 以降で導入されたgit switch (ブランチ切り替え)とgit restore (変更の取り消し)を中心に紹介します。役割が明確に分かれていて、初心者が混乱しにくいのが利点です。checkout でも同じことはできますが、これから覚えるなら新しい方をおすすめします。
まずは全体像をつかむ
細かいコマンドに入る前に、これから扱うワークフローの全体像を一枚の図で見ておきましょう。main (本番相当)と作業ブランチfeature が、どこで分かれ・どこで合流するのかを意識すると、後の各ステップが頭に入りやすくなります。
1. 基本操作 ― ローカル ⇄ リモートの push / pull
まず Git の世界には2つの「置き場所」があります。手元のPCにある ローカルリポジトリ と、GitHubなどのサーバー上にある リモートリポジトリ です。この2つの間でコードを行き来させるのがpush /pull です。
💻
ローカルリポジトリ
自分のPC内
push
pull / clone
☁️
リモートリポジトリ
GitHub / GitLab など
| コマンド | 向き | 意味 |
|---|---|---|
git clone | リモート→ローカル | リモートのリポジトリを丸ごと手元に複製(初回のみ) |
git add / commit | ローカル | 変更を記録(履歴をローカルに刻む)。まだサーバーには送られない |
git push | ローカル→リモート | ローカルのコミットをリモートへアップロード |
git pull | リモート→ローカル | リモートの最新を取得して手元にマージ(fetch +merge ) |
git fetch | リモート→ローカル | 取得だけ。手元の作業には まだ反映しない |
Step 1:リポジトリを手元に複製する(clone)
最初の一回だけ
# リモートのリポジトリを手元にコピーする
$ git clone https://github.com/your-team/your-app.git
# Cloning into 'your-app'...
# Receiving objects: 100% (215/215), done.
# 作成されたフォルダに移動
$ cd your-app Step 2:変更を記録する(add → commit)
ファイルを編集したら、 「ステージング → コミット」 の2段階で履歴に記録します。ここまでは すべてローカルでの作業 で、サーバーには一切影響しません。
# 変更されたファイルを確認する
$ git status
# modified: src/login.ts
# 記録したい変更をステージングする(. は全ての変更)
$ git add src/login.ts
# コミット(履歴として確定)。-m でメッセージを付ける
$ git commit -m "ログイン画面の文言を修正"
# [main 4f2a9c1] ログイン画面の文言を修正
# 1 file changed, 3 insertions(+), 1 deletion(-)✨ コミットメッセージのコツ
「何を・なぜ変えたか」が後から分かる短い文にします。「修正」「fix」だけだと、履歴を見返したときに役に立ちません。ログインボタン押下時のnullエラーを修正 のように具体的に書きましょう。
Step 3:リモートへ送る(push)/受け取る(pull)
ローカルにたまったコミットをサーバーへ送るのがpush 、サーバーの最新を手元に取り込むのがpull です。 ここで初めてリモートに影響します。
# 【リモートへ送る】ローカルのコミットをサーバーへ反映
$ git push origin main
# To https://github.com/your-team/your-app.git
# 1a2b3c4..4f2a9c1 main -> main
# 【リモートから取得】他の人の変更を手元に取り込む(作業前に必ず!)
$ git pull origin main
# Updating 4f2a9c1..7d8e9f0
# Fast-forward
src/header.ts | 5 +++++🔍 「作業を始める前に pull」を習慣に
チーム開発では、自分が作業していない間に他の人がコードを更新しています。 作業を始める前に必ずgit pull する 習慣をつけると、後述の「コンフリクト(衝突)」をぐっと減らせます。git pull は内部的にfetch (取得)とmerge (合流)をまとめて行っています。
2. ブランチ運用 ― mainは本番、作業はブランチで
ここからが運用の肝です。基本方針はシンプルで、main ブランチは常に「本番環境と同じ状態」に保ち、機能追加や改修は別のブランチで行う 、というものです。
❓ なぜブランチを分けるのか
main に直接コードを書き込むと、開発途中の 動かないコード が本番相当のブランチに混ざってしまいます。作業をfeature ブランチに隔離しておけば、main はいつでもリリースできる状態を維持でき、急な本番修正にもすぐ対応できます。
Step 1:mainを最新にしてからブランチを切る
分岐の出発点となるmain は、必ず最新にしておきます。古いmain から枝分かれすると、後の統合が面倒になります。
# mainブランチに切り替え(switch)
$ git switch main
# 【リモート】mainを最新の本番コードにそろえる
$ git pull origin main
# 作業用ブランチを作って同時に切り替える(-c = 新規作成)
$ git switch -c feature/user-profile
# Switched to a new branch 'feature/user-profile'✨ ブランチ名の付け方
役割が分かる接頭辞を付けるのが一般的です。新機能はfeature/ 、バグ修正はfix/ 、緊急修正はhotfix/ など。例:feature/user-profile 、fix/login-validation 。チームで命名ルールを決めておくと一覧性が上がります。
Step 2:ブランチ上で作業してコミットする
あとは普段どおりadd →commit を繰り返します。 この間、main はまったく影響を受けません。 いま自分がどのブランチにいるかはgit branch で確認できます(* が現在地)。
# いまどのブランチにいるか確認
$ git branch
# * feature/user-profile ← * が現在地
# main
# 機能を実装してコミット
$ git add .
$ git commit -m "プロフィール編集フォームを追加" Step 3:作業ブランチをリモートにも push する
手元だけで作業していると、PCが壊れたら消えてしまいます。バックアップとレビューのため、ブランチもリモートに push しておきましょう。 初回だけ-u を付ける のがポイントです。
# 初回:リモートに同名ブランチを作り、追跡関係を設定する(-u)
$ git push -u origin feature/user-profile
# Branch 'feature/user-profile' set up to track 'origin/feature/user-profile'.
# 2回目以降は追跡先が分かっているので git push だけでOK
$ git push✨ -u(--set-upstream)とは
「このローカルブランチは、リモートのこのブランチと対応している」という 追跡(tracking)関係 を設定するオプションです。一度設定すれば、以降はgit push /git pull と打つだけで対応するリモートブランチとやり取りできます。
3. 緊急対応 ― 作業中に本番の急ぎ修正が入ったら
ありがちな状況です。feature/user-profile で機能開発を進めている最中に、 「本番でログインエラーが出ている、今すぐ直して!」 という連絡が入りました。 ここでやるべきことは2段階です。まず 本番相当のmain を修正してリリース し、次に その修正を作業中のfeature ブランチにも取り込む 。順番に見ていきましょう。
Step 1:作業中の変更を一時退避する(stash)
いまのfeature ブランチには、コミットしていない中途半端な変更があるかもしれません。そのままブランチを切り替えるとエラーになることがあるので、git stash で一時退避します。(区切りが良ければ普通にコミットしてもOKです。)
# 作業中の変更を退避棚(stash)に一時保管する
$ git stash push -m "プロフィール機能 作業中"
# Saved working directory and index state On feature/user-profile: プロフィール機能 作業中 Step 2:mainで修正する(hotfixブランチ推奨)
main に切り替え、最新の本番コードにそろえてから修正します。直接main をいじってもよいですが、 修正専用のhotfix ブランチ を切るとレビューや巻き戻しがしやすく安全です。
# mainへ切り替え
$ git switch main
# 【リモート】本番の最新状態にそろえる
$ git pull origin main
# 修正用ブランチを切る
$ git switch -c hotfix/login-error
# ... コードを修正 ...
$ git add src/login.ts
$ git commit -m "ログイン時のnull参照エラーを修正" Step 3:修正をmainに取り込み、本番へリリースする
# mainに戻って、hotfixの内容をマージ
$ git switch main
$ git merge hotfix/login-error
# Updating 7d8e9f0..a1b2c3d
# Fast-forward
# 【リモート】mainをサーバーへ反映 → ここから本番デプロイ
$ git push origin main
# 7d8e9f0..a1b2c3d main -> main ← 本番反映完了🎯 ここまでで本番の火は消えた
main に修正が入り、リモートへ push されました。あとはいつものデプロイ手順(CIや手動デプロイ)で本番に反映すれば、緊急対応はひとまず完了です。 ただし、まだ作業中のfeature ブランチにはこの修正が入っていません。 次のステップで取り込みます。
Step 4:修正を feature ブランチにも取り込む
作業ブランチに戻り、退避していた変更を戻したうえで、main の修正をマージして取り込みます 。これをやらないと、せっかく直した本番バグが、機能リリース時に 復活 してしまいます。
# 作業ブランチに戻る
$ git switch feature/user-profile
# 退避していた作業を復元する
$ git stash pop
# mainの最新(=hotfixを含む)を作業ブランチに取り込む
$ git merge main
# Merge made by the 'ort' strategy.
src/login.ts | 4 ++--⚠️ ️ コンフリクト(衝突)が出たら
main の修正箇所と、自分がfeature で触っていた箇所が重なると、CONFLICT と表示されます。慌てなくて大丈夫です。該当ファイルを開くと<<<<<<< 〜>>>>>>> のマークで両方の変更が示されるので、正しい形に手で編集し、git add →git commit で確定すれば解決です。詳しい手順はこの記事末尾のトラブルシュートにもまとめています。
❓ merge と rebase、どちらで取り込む?
main の更新を作業ブランチに取り込む方法にはgit merge main とgit rebase main の2つがあります。 merge は履歴をそのまま残す安全な方法で、複数人が同じブランチを共有している場合に向きます。 rebase は履歴を一直線に整えられて見やすい反面、すでに push 済みのブランチで使うと履歴が書き換わり混乱の元になります。 迷ったら merge が安全です。
4. リリースとマージ ― 機能完成後にmainへ統合する
feature/user-profile での機能追加とテストが完了し、本番リリースの準備が整いました。最後に、この作業ブランチをmain に統合します。やり方は大きく2通りです。
| 方法 | こんなとき | 特徴 |
|---|---|---|
| Pull Request(PR)経由 | チーム開発・レビューが必要なとき | GitHub等の画面でレビュー・承認してからマージ。 推奨 |
| ローカルで直接 merge | 個人開発・小さな変更 | 手元でgit merge して push するシンプルな方法 |
方法A:Pull Request(チーム開発の定番)
作業ブランチを push したあと、GitHub/GitLab の画面でfeature/user-profile →main への Pull Request を作成します。レビュアーが差分を確認し、承認後に画面上の「Merge」ボタンでmain に統合します。 第三者の目が入る のが最大の利点で、本番相当のmain を守る安全弁になります。
# 作業ブランチの最新をリモートへ push(この後ブラウザでPRを作成)
$ git switch feature/user-profile
$ git push
# remote: Create a pull request for 'feature/user-profile' on GitHub by visiting:
# remote: https://github.com/your-team/your-app/pull/new/feature/user-profile マージ後は、ローカルのmain を最新化して、リモートの統合結果を取り込んでおきます。
# PRがマージされたら、手元のmainも最新化しておく
$ git switch main
$ git pull origin main 方法B:ローカルで直接マージする
個人開発などでPRを使わない場合は、手元でマージして push します。
# mainへ切り替えて最新化
$ git switch main
# 【リモート】mainを最新に
$ git pull origin main
# 作業ブランチをmainに統合
$ git merge feature/user-profile
# Updating a1b2c3d..e5f6g7h
# src/profile.ts | 48 ++++++++++++++++++
# 【リモート】統合結果を本番相当のmainとして反映
$ git push origin main 補足:Fast-forward と --no-ff の違い
上の例の出力にUpdating a1b2c3d..e5f6g7h と出ているとおり、Gitは条件がそろうと 「Fast-forward(早送り)」 という方式で統合します。これは--no-ff オプションを付けるかどうかで挙動が変わる、運用上とても重要なポイントです。
Fast-forwardが起きるのは、 分岐したあとmain 側に新しいコミットが1つも無い 場合です。このときGitは新しいコミットを作らず、mainポインタを作業ブランチの先端まで前進させるだけで済ませます。結果として履歴は一直線になり、 ブランチが存在した痕跡は残りません 。
一方、git merge --no-ff を付けると、Fast-forwardが可能な場合でも 必ず「マージコミット」を1つ作ります 。作業ブランチのコミット群がそのマージコミットの下にまとまり、履歴に「ここで機能ブランチを統合した」という事実がはっきり残ります。
# 【デフォルト】条件がそろえばFast-forward(マージコミットなし)
$ git merge feature/user-profile
#Updating a1b2c3d..e5f6g7h
#Fast-forward
# src/profile.ts | 48 ++++++++++++++++++
# --no-ff:Fast-forward可能でも必ずマージコミットを作る
$ git merge --no-ff feature/user-profile
#Merge made by the 'ort' strategy.
# src/profile.ts | 48 ++++++++++++++++++| 項目 | 通常の merge(Fast-forward | merge --no-ff |
|---|---|---|
| マージコミット | 作られない | 必ず作られる |
| 履歴の見た目 | 一直線でフラット | 分岐と合流が残る |
| ブランチの痕跡 | 消える | 残る |
| 機能まるごとの取り消し | コミットを個別に戻す必要がある | マージコミット1つをrevert すればOK |
| いつ統合したかの記録 | 追いにくい | マージコミットに残り追いやすい |
❓ どちらを使うべき? 用途別の使い分け
Fast-forward(デフォルト)が向く場面: 個人開発や小さな変更で、履歴をできるだけシンプルに保ちたいとき。コミットがすでにきれいに並んでいて、「ブランチがあった」という情報を残す必要がないケースです。
--no-ff が向く場面: チーム開発で「いつ・どの機能を入れたか」を後から追いたいとき、機能単位でレビューや巻き戻しをしたいとき。マージコミットが機能の区切りになるため、不具合が出てもそのコミット1つをgit revert すれば機能まるごとを安全に取り消せます。git-flow などの運用ルールでは--no-ff を標準とすることが多いです。
💡 main側に変更があるときは自動でマージコミット
--no-ff が効くのは「Fast-forwardが可能なとき」だけです。分岐後にmain 側にも別のコミットが入って履歴が枝分かれしている場合は、オプションの有無にかかわらず 自動的にマージコミットが作られます 。また、Fast-forwardでしか統合したくない(できなければ失敗させたい)場合はgit merge --ff-only という第3の選択肢もあります。チームではgit config merge.ff false でリポジトリ全体の既定を--no-ff に固定する運用もよく使われます。
Step:役目を終えたブランチを削除する
統合が済んだ作業ブランチは、ローカルとリモートの両方から削除して整理します。残しておくとブランチ一覧が散らかります。
# 【ローカル】マージ済みの作業ブランチを削除(-d は安全削除)
$ git branch -d feature/user-profile
# Deleted branch feature/user-profile (was e5f6g7h).
# 【リモート】サーバー上のブランチも削除
$ git push origin --delete feature/user-profile✨ -d と -D の違い
-d は「マージ済みのときだけ削除」する安全なオプション。まだ統合していないブランチを誤って消す事故を防げます。どうしても未マージのブランチを破棄したいときだけ-D (強制削除)を使います。
5. チートシート & トラブルシュート
日常で使うコマンド早見表
| コマンド | コマンド説明 |
|---|---|
| git clone <url> | リモートを手元に複製する(最初の一回) |
| git status | 変更状況・現在のブランチを確認する。困ったらまずこれ |
| git add . / git commit -m "..." | 変更をステージングして履歴に記録する(ローカル) |
| git push / git pull | リモートへ送る/リモートから取り込む |
| git switch -c <branch> | ブランチを新規作成して切り替える |
| git switch <branch> | 既存ブランチに切り替える |
| git merge <branch> | 指定ブランチの内容を現在のブランチに取り込む |
| git stash / git stash pop | 作業中の変更を一時退避/復元する |
| git branch -d <branch> | マージ済みのブランチを安全に削除する |
よくあるトラブル
❓ push したら rejected と言われて送れない
あなたが push する前に、誰かが先にリモートを更新しています。まずgit pull origin main でリモートの変更を取り込み(必要ならコンフリクトを解消し)、それからgit push し直してください。
❓ merge で CONFLICT が出てしまった
衝突したファイルを開くと<<<<<<< HEAD (自分の変更)と>>>>>>> (取り込む側の変更)が並びます。正しい内容に手で書き直してマーカーを消し、git add <file> →git commit で確定すれば解決します。git status がどのファイルを直すべきか教えてくれます。
❓ 間違えて main で作業を始めてしまった
まだコミットしていなければ、git stash で退避 →git switch -c feature/xxx で正しいブランチを作成 →git stash pop で変更を移せます。作業内容を失わずにブランチを付け替えられます。
❓ 直前のコミットメッセージを間違えた
まだ push していなければgit commit --amend -m "正しいメッセージ" で直せます。 すでに push 済みの場合 は履歴の書き換えになるため、共有ブランチでは避けるのが無難です。
❓ 変更を全部なかったことにしたい(コミット前)
特定ファイルの変更を捨てるならgit restore <file> 、ステージングだけ取り消すならgit restore --staged <file> を使います。古い記事のgit checkout -- <file> と同じ役割を、より分かりやすい名前で果たします。
まとめ
今回学んだこと
- ローカル(add/commit)とリモート(push/pull)の境界を意識して操作できる
mainを本番相当に保ち、作業はfeatureブランチに隔離する運用- ブランチは
git switch -cで作成、初回 push は-u付き - 本番の緊急修正は「mainを直してリリース → 作業ブランチに
merge mainで取り込む」の2段構え - 機能完成後は PR もしくは
git mergeでmainに統合し、不要ブランチを削除 - 困ったら
git status。コンフリクトもマーカーを直してadd → commitで解決
🚀
これで日々のソース管理は回せます
push/pull の基本から、mainを守るブランチ運用、本番への緊急対応、そして機能の統合まで
――
一連の流れを「ローカルかリモートか」を意識しながら通しで追えるようになりました。あとは実際のリポジトリで手を動かすほど、自然と身についていきます。
✅ push / pull
✅ ブランチ運用
✅ 緊急hotfix対応
✅ mainへの統合
✅ コンフリクト解消
