Gitの基礎とブランチモデル

目次

Gitの基本構造

Gitは「分散型バージョン管理システム」と呼ばれ、ソースコードなどのファイル履歴をローカルで管理しつつ、必要であればリモートに保存・共有することができます。

従来のバージョン管理システムがファイルの「差分」を履歴として持つのに対し、Gitは各ファイルの「スナップショット(状態)」を履歴として記録するのが特徴です。各コミット時点でのプロジェクトの状態をまるごと管理しているイメージです。

Gitでは以下4つの場所(状態)を管理します。

  1. 作業ディレクトリ
    • 実際に作業中のファイルが置かれる場所
    • ファイルを新規作成・編集・削除する
  2. ステージングエリア
    • 次のコミット(履歴)に含めたいファイルを置く場所
    • git add コマンドで登録する
  3. ローカルリポジトリ
    • ステージングエリアにある変更を確定し、履歴として保存する場所
    • git commitコマンドで実行
    • これにより、自分のPC内の.gitディレクトリに変更履歴(スナップショット)が蓄積されていく
  4. リモートリポジトリ
    • チーム開発などで複数人とコード共有する場所
    • git pushでローカルリポジトリの変更をリモートリポジトリに送る
    • git pullでリモートリポジトリの変更をローカルへ反映する

Gitによるファイル管理の流れ/よく使うコマンド

1. Gitリポジトリの初期化

a. 新規でGit管理を始める

git init

まだGit管理されていないプロジェクトディレクトリで .git を作成する

b. 既存のリモートリポジトリからGit管理を始める

git clone <リポジトリのURL>

GitHubやGitLabなどのリモートリポジトリからソースコードをローカルに複製(クローン)し、.git を含んだ作業ディレクトリを作成する

2. 作業ディレクトリ関連

a. ワークツリーやステージングエリアの状態を確認

git status

以下がそれぞれ表示される

  • 未追跡(新規)ファイル、内容変更されたファイル
  • ステージング済み(次回コミット予定)のファイル

b. 変更内容の差分を比較表示

# ワークツリー全体の差分
git diff

# ステージングエリア - ローカルリポジトリ間の差分
git diff --staged

c. ワークツリーの変更を元に戻す

# ステージング前の変更内容を取り消す
git restore <ファイル>

# ステージングされた変更も含めすべて取り消す
git restore --staged <ファイル>

d. ワークツリーの変更を一時的に退避する

git stash
git stash -u  # 未追跡ファイルも含める
git stash -m "メッセージ"  # メッセージ付き

# stashした作業一覧を確認
git stash list

# 最後にstashした変更を復元
git stash apply
# 最後にstashした変更を削除
git stash drop
# 最後にstashした変更を復元・削除
git stash pop
  • 作業内容をコミットせず別のブランチへ切り替えたい場合など
  • 復元・削除するstashは一覧表示されるstash名で指定することができる 例)git stash apply stash{2}

3. ステージングエリア関連

a. 次回コミットに含める変更ファイルをステージングエリアへ登録する

git add <ファイル>

# 変更ファイルすべてをステージング
git add .

4. ローカルリポジトリ関連

a. ステージングエリアにある変更を履歴として確定し、ローカルリポジトリへ保存する

git commit -m "コミットメッセージ"

# 直前のコミットを修正する
git commit --amend

b. コミット履歴を表示

git log

# 履歴を1行表示
git log --oneline
# ブランチ構造をツリー状に表示
git log --graph

c. ブランチを表示・作成・削除

# ブランチ一覧表示
git branch

# 新規ブランチ作成
git branch <ブランチ>

# ブランチ削除
git branch -d <ブランチ>

d. ブランチの切り替え・特定のコミットへの移動

git switch <ブランチ>
# ブランチを新規作成して切り替え
git switch -c <ブランチ>

# 旧来の書き方
git checkout <ブランチ>

e. ブランチ同士の変更を統合する(マージ)、または履歴をベースから組み替える(リベース)

# 指定ブランチを現在のブランチに統合
git merge <ブランチ>

# 指定ブランチをベースに現在のブランチ変更をリベース(元とは別のコミットとして置き換えられる)
git rebase <ブランチ>
  • GitHubなどにプッシュしたコミットをリベースしないこと(ローカルとリモートで過去の共有履歴が一致しなくなるため混乱の原因に)

f. コミットを取り消す(リセット)、過去のコミットに戻す(リバート)

# コミットだけ取り消し、変更をステージングに残す
git reset <コミットID> --soft
# コミットも変更内容をすべて取り消す
git reset <コミットID> --hard

# 過去のコミットに戻す(履歴として残る)
git revert <コミットID>
  • 「間違ったコミットをしてしまった」「特定のコミットだけ取り消したい」などの場合
  • reset履歴を巻き戻すため、チーム開発の共有履歴で使用する場合は注意
  • revert取り消し用の新しいコミットを作り、共有履歴を壊さないのでこちらが推奨される

5. リモートリポジトリとの連携

a. ローカルリポジトリのコミットをリモートリポジトリ(origin)に送信

git push origin <ブランチ>

b. リモートリポジトリの最新の変更をローカルに取り込む(git fetch + git merge

git pull origin <ブランチ>

c. リモートリポジトリの更新履歴をローカルのリモート追跡ブランチに取り込む

git fetch origin
  • 「リモートにどんな変更があるか」だけを確認したいとき
  • ローカルの作業ブランチには適用されていない(手動でgit mergegit rebase する)

ブランチモデル

ブランチとは、プロジェクト本体から作業を分離させることで、本体に影響を与えず複数人で同時開発できる仕組みのことです。

ブランチモデルはチーム開発での混乱を避けるために「どのように枝分かれを管理するか」を明確にルールとして定めたものとなります。

基本概念

チーム開発でよく使われる代表的なブランチモデルには以下のようなものがあります。

  • Git Flow
  • GitLab Flow
  • GitHub Flow
  • Trunk-Based Development

ここでは比較的導入しやすいといわれる Git FlowGitHub Flow を紹介します。

1. Git Flow

  • Vincent Driessen氏が提唱したモデル
  • ブランチを複数に分けることで、安定版のリリースやバグ修正、次期開発中のコードなどを明確に分離できる
  • 主なブランチ
    1. main リリース済みの安定したソースコード。本番リリース用
    2. develop 日常的な開発のベースとなる。次にリリースされる機能がまとまる
    3. feature 個別の新機能開発や修正を行う。完了後にdevelopブランチに統合する
    4. release リリースの準備(テストやバグ修正)を行う。リリースが完了したらmainにマージし、developにも反映する
    5. hotfix リリース後に見つかった緊急の不具合を修正する。mainから作成し、修正後はmaindevelopの両方にマージする
  • メリット:複数バージョンのリリースを並行管理しやすい(バージョン管理が複雑になりがちなプロジェクト向き)
  • デメリット:ブランチが増えがちで、規模が大きくなるほど運用コストが上がる

2. GitHub Flow

  • GitHub社が提唱するシンプルなモデル
  • 一般的なルール
    1. mainブランチは常にデプロイ可能な状態を保つ
    2. 新しい機能や修正を行う場合はfeatureブランチを作成する
    3. 開発が完了したらプルリクエスト(後述) を作成する
    4. レビュー完了後、問題なければmainブランチにマージする
    5. 必要に応じてデプロイ(自動or手動)
  • メリット:シンプルで運用しやすい、プルリクエストを中心とした開発フローに適している(小規模〜中規模のプロジェクト向き)
  • デメリット:大規模プロジェクトになると、リリースの長期安定版を管理しにくい場合がある

プルリクエスト(PR : Pull Request)

GitHubなどのホスティングサービス上で、他のブランチへの変更を提案してレビューやマージを行うための仕組みです。

1. PR作成〜マージの流れ

  1. mainブランチから派生ブランチを作成(例: feature/add-user-auth
  2. 派生ブランチで作業・コミットし、変更をリモートリポジトリにプッシュする
  3. GitHubなどでPRを作成
  4. チームメンバーにコードレビューしてもらい、修正があれば対応する
  5. 問題ないと判断されたらPRをマージし、mainブランチを更新
  6. 不要になったfeatureブランチは削除

2. ポイント

  • 1PR = 1機能 or 1修正 が基本的な単位。レビューのしやすさも考慮してできるだけ小さめにまとめる
  • コミット単位では、さらに小さな意味のある塊になるよう分割すると後から履歴をたどりやすい

GitHub Flowベースのブランチ運用例

  1. メンバー全員がmainブランチをローカルにcloneし、最新状態を常に保つ
  2. 作業単位でfeatureブランチを作成 例)git switch -c feature/login-page
  3. ローカルで作業し、コミットをこまめに行う 例)git commit -m "ログイン機能の追加"
  4. ある程度区切りがついたらリモートにプッシュし、GitHub上でPRを作成
  5. 他メンバーにレビューを依頼し、変更差分を確認してもらう
  6. レビューで指摘があれば修正し、再度プッシュして同じPRをアップデートする
  7. 問題がなければマージし、mainブランチに変更を反映する
  8. 不要になったfeatureブランチは削除する

参考サイト

Git

Atlassian Git Tutorial:Branching Workflows

https://www.atlassian.com/git/tutorials/comparing-workflows

GitHub:About pull requests

https://docs.github.com/ja/pull-requests

「Git」に関連する記事