GitHub入門 — リモートリポジトリ・Pull Request・Issue を Terraform 管理で実践するハンズオン

📚 関連記事 — Git/GitHub × Terraform実践シリーズ


目次

Section 1: この記事について

1-1. シリーズ位置付けと第1弾から継承するリポジトリ

本記事は「Git/GitHub × Terraform実践シリーズ」の第2弾です。第1弾「Git入門」では、ローカル環境でリポジトリを作成し、コミット・ブランチ・マージという Git の基本操作を Terraform コードを題材に実践しました。

第2弾では、その「ローカル完結」から一歩踏み出し、チーム協業に不可欠なリモートリポジトリとの連携を学びます。GitHub を使うことで、コードを世界中からアクセス可能なクラウドに保存し、Pull Request によるコードレビュー、Issue によるタスク管理、fork による OSS コントリビューションが可能になります。

第1弾を終えた段階で、あなたのローカルには以下の状態のリポジトリが完成しています。このリポジトリを第2弾でも引き続き使います。

ファイル/ディレクトリ内容
terraform-git-handson/ルートディレクトリ(Git 管理済み)
.gitignore.terraform/*.tfstate*.tfstate.backup*.tfvars を除外済み
main.tfAWS プロバイダ設定(us-east-1 リージョン)
variables.tfvpc_cidrenvironment などの変数定義
outputs.tfvpc_idsubnet_ids などの出力値定義
modules/vpc/main.tfVPC・サブネット・インターネットゲートウェイのリソース定義
modules/vpc/variables.tfモジュール変数定義
modules/vpc/outputs.tfモジュール出力値定義

コミット履歴は次のようになっているはずです。

git -C terraform-git-handson log --oneline --graph --all
*Merge: add VPC module
|\
| * feat: add VPC module (modules/vpc)
| * feat: define variables for VPC module
|/
* feat: add provider configuration
* chore: add .gitignore

この履歴を持ったリポジトリを GitHub にプッシュするところから第2弾が始まります。

本記事の全セクション構成

本記事は全 10 セクションで構成されています。

セクションタイトル内容の核心
Section 1この記事についてシリーズ位置付け・学習ゴール・前提条件・進め方
Section 2GitHubとはGit vs GitHub・サービス比較・Terraform エコシステムとの関係
Section 3アカウント + 認証設定SSH key・PAT・GitHub CLI の 3 方式設定ハンズオン
Section 4リモートリポジトリ作成 + 初回 pushgit remote addgit push -u origin main・README 整備
Section 5push / pull / fetch の動作原理リモート追跡ブランチの仕組み・git pull の内部分解・衝突対処
Section 6Pull Request ハンズオンfeature ブランチ→PR→レビュー→マージ の協業フロー体験
Section 7Issues と ProjectsIssue 起票・テンプレート・PR 自動クローズ・カンバン管理
Section 8Fork & 安全な取り消しfork → upstream 追従・git revert で push 済みコミット取り消し
Section 9リポジトリ運用 Tipsブランチ保護・CODEOWNERS・Secret Scanning・よくあるエラー
Section 10まとめ・次のステップ習得スキル表・第3弾予告・参考リンク集

1-2. この記事で学ぶこと

第1弾の Section 9-2「次のステップ」で予告した 6 テーマを、本記事でそれぞれ体系的に学びます。

テーマセクション学ぶ内容
リモートリポジトリSection 4GitHub でリポジトリを作成し、git remote add で連携する
push / pull / fetchSection 5git push でローカルの変更をリモートへ送り、git pull でリモートの変更を取り込む仕組みと使い分けを理解する
Pull RequestSection 6feature ブランチの変更を PR として提出し、差分をチームでレビューしてマージする協業フローを体験する
Issue 連携Section 7コミットメッセージ・PR で Issue 番号を参照し、自動クローズ・Projects ボードでタスク管理する
fork & cloneSection 8OSS コントリビューションの基本フロー(fork → clone → 修正 → PR)を体験する
push 済みコミットの安全な取り消しSection 8git revert で履歴を書き換えずに取り消しコミットを追加し、git reset --hard との違いを理解する

さらに本記事では、GitHub を CLI で操作できる GitHub CLI(gh コマンド) の使い方も随所に組み込んでいます。GUI 操作と CLI 操作を対比しながら学ぶことで、どちらの文脈でも即戦力として動ける力が身につきます。

第2弾を通じて到達する状態

本記事を完走すると、以下の状態になります。

  • terraform-git-handson/ リポジトリが GitHub に公開(または Private として)ホスティングされている
  • git pushgit pull が SSH 認証で動作している
  • Pull Request によるコードレビューフローを一通り体験した
  • Issue → PR → Issue 自動クローズのサイクルを実践した
  • gh コマンドで PR 作成・リポジトリ作成が CLI で完結できる
  • git revert で push 済みコミットを安全に取り消せる

第1弾との対比で理解する学習範囲

第1弾と第2弾を並べて見ると、ローカル操作→リモート協業への拡張が明確になります。

操作種別第1弾(ローカル完結)第2弾(リモート連携)
リポジトリgit init で作成GitHub でホスティング
変更の保存git commitgit commit + git push
他者との共有できないPR・Issue で協業
変更の取り込みローカルブランチ間git pull / git fetch
変更の取り消しgit reset / git stashgit revert(push 済みコミット安全取り消し)
作業の可視化git loggit graphGitHub UI・Projects ボード

1-3. 前提条件

本記事を最大限に活用するために、以下の前提条件をすべて満たしていることを確認してください。

前提条件確認方法満たせていない場合
第1弾「Git入門」を完了しているgit -C terraform-git-handson log --oneline でコミット履歴が確認できる第1弾を先に実施する
terraform-git-handson/ がローカルに存在するls terraform-git-handson/第1弾のハンズオンを最初からやり直す
Git がインストールされている(v2.30 以上推奨)git --versionGit 公式サイト(git-scm.com)からインストール
ターミナル操作の基礎があるcdlscat が使える第1弾が完了していれば満たしているはず
インターネット接続があるcurl https://github.com が成功するネットワーク設定を確認する

Terraform のインストールは不要です。 本記事では terraform apply を実行しないため、Terraform CLI がインストールされていなくても全ハンズオンが完結します。ただし第5弾以降では Terraform CLI が必要です。

OS について: 本記事のコマンドは macOS と Ubuntu/Debian 系 Linux で動作確認しています。Windows をお使いの場合は WSL2(Windows Subsystem for Linux)をインストールしてから Ubuntu 環境で実施してください。


1-4. 学習の進め方

本記事は Section 1 → Section 10 の順に通読しながらハンズオンを実施する 構成になっています。各セクションは前のセクションの作業結果を引き継ぐため、途中のセクションから読み始めるとコマンドが正しく動作しない場合があります。

学習の大きなフローを以下に示します。

フェーズセクションやることハンズオンの主な作業場所
準備Section 1〜3GitHub アカウント作成・認証設定(SSH/PAT/gh)ターミナル + ブラウザ
リモート連携基礎Section 4〜5リポジトリ作成・初回 push・pull/fetch の理解ターミナル + GitHub.com
協業実践Section 6〜7PR・レビュー・Issue・Projects でチーム開発を体験ターミナル + GitHub.com
発展操作Section 8fork・upstream 追従・git revertターミナル
運用・トラブルSection 9ブランチ保護ルール・CODEOWNERS・よくあるエラー対処GitHub.com + ターミナル
振り返りSection 10習得スキル一覧・第3弾予告・参考リンク読み物

各ハンズオン手順は [ハンズオン] と明示しています。読み物部分を読んでコンセプトを理解してから、[ハンズオン] の手順をターミナルで実行する流れが最も効率的です。

推奨環境: 画面を2分割し、左側にブラウザ(GitHub.com)、右側にターミナルを配置すると作業が快適です。


1-5. 想定所要時間と AWS 課金なし宣言

想定所要時間: 約 150 分

フェーズセクション目安時間備考
準備・認証設定Section 1〜3約 30 分アカウント作成済みなら 20 分
リモート連携基礎Section 4〜5約 35 分git push の初回は慎重に
PR・Issue・協業実践Section 6〜7約 50 分コードレビューの体験が核心部分
発展・まとめSection 8〜10約 35 分fork のハンズオンは時間に余裕を持って

AWS 課金は一切発生しません。 本記事を通じて terraform apply は実行しません。Terraform コードはあくまで GitHub での管理対象として使用します。AWS リソースの作成・変更・削除は行わないため、AWS アカウントや クレジットカードの登録は必要ありません。

GitHub 無料プランで完結します。 Private リポジトリ・Actions・ブランチ保護ルールのうち、本記事で必要なものはすべて無料プランの範囲内で利用できます。課金が発生するのは、Team プラン以上でしか使えない機能(高度なブランチ保護・SAML SSO など)のみです。本記事ではそれらを扱いません。


Section 2: GitHubとは — Gitホスティングの役割とエコシステム

2-1. Git と GitHub の違い(ツール vs サービス)

「Git と GitHub は何が違うのか?」という質問は、初学者がよく抱く疑問の代表格です。第1弾でも軽く触れましたが、第2弾に進む前に改めて整理します。

比較軸GitGitHub
種別バージョン管理システム(ソフトウェア)Git リポジトリのホスティングサービス(クラウド)
提供形態オープンソース CLI ツール(Linus Torvalds 作)Microsoft 社が 2018 年に買収・運営する Web サービス
動作場所ローカルマシン上(インターネット不要)クラウド上(github.com でアクセス)
主な機能コミット、ブランチ、マージ、diff、logリポジトリ公開・共有、PR、Issue、Actions、Discussions
インストールapt install git / brew install gitブラウザでアクセスするのみ(インストール不要)
類似例えMicrosoft Word(文書編集ソフト)Google Drive(クラウド共有・コラボサービス)
なくても動くGitHub なしで完全に動作するGit なしでは利用価値がない(リポジトリの中身が Git)

重要な認識: Git は GitHub がなくても動作します。第1弾では GitHub を一切使わずに Git の操作を完結させました。しかし実務では、チーム開発・コードレビュー・CI/CD を実現するために Git リポジトリを GitHub のようなサービスでホスティングすることが標準的です。

なぜ GitHub が「事実上の標準」になったか

Git は 2005 年に Linus Torvalds が Linux カーネル開発のために作成したツールです。一方 GitHub は 2008 年にサービスを開始し、オープンソースプロジェクトの集積地として急速に普及しました。現在は 1 億人以上の開発者が利用する世界最大のコードホスティングサービスです。Terraform のエコシステム全体が GitHub を中心に構築されているため、本シリーズでも GitHub を標準として採用します。


2-2. 他サービスとの比較と選定指針

GitHub 以外にも、Git リポジトリをホスティングするサービスは複数存在します。選定時の参考に主要サービスを比較します。

サービス運営元特徴Terraform との親和性
GitHubMicrosoft世界最大のシェア。Actions・OIDC・Packages が強力Terraform Registry 公式モジュールの大半が GitHub 管理。OIDC 連携(第5弾)は GitHub Actions が基準
GitLabGitLab IncCI/CD がビルトイン(GitLab CI)。Self-hosted 版あり。Issues・MR が充実gitlab Terraform プロバイダが公式サポート。セキュリティスキャンが充実
BitbucketAtlassianJira・Confluence との統合が得意。Pipelines で CI/CD 可能Jira 連携が必要な企業向け。Atlassian スタックと統一したい場合に選択
Giteaコミュニティ軽量・Self-hosted 専用 OSS。Go 製で低リソース動作オンプレミス Terraform 環境や閉域 VPC 内の Git サーバーとして最適
Azure DevOps ReposMicrosoftAzure DevOps エコシステムと統合。Boards・Pipelines が連携Azure プロバイダを主に使う場合に親和性高。Azure OIDC 連携が容易
AWS CodeCommitAmazonAWS との統合。IAM で認証制御2024年4月に新規顧客向けサービス終了(既存ユーザーは継続利用可)。今後の新規採用は非推奨

本シリーズでの選択: GitHub

本シリーズでは GitHub を使用します。理由は次の 3 点です。

  1. Terraform Registry との連携: registry.terraform.io に公開されているモジュールの大半は GitHub リポジトリとして管理されており、バグ報告・PR 提出の標準的な窓口が GitHub
  2. GitHub Actions × OIDC: 第5弾で学ぶ CI/CD 自動化(terraform plan/apply の自動化)は GitHub Actions と AWS OIDC の連携が前提
  3. 無料プランの充実: パブリック・プライベートリポジトリともに無制限、Actions 月 2,000 分無料で学習コストがほぼゼロ

2-3. GitHub の主要機能概観

GitHub は単なるコードホスティングサービスではなく、ソフトウェア開発全般を支援するプラットフォームです。本シリーズで登場する機能を中心に概観します。

機能概要本シリーズでの登場
Repository(リポジトリ)Git リポジトリのホスティング。Public/Private を選択可能。ファイルブラウザ・コミット履歴閲覧が GUI で操作できるSection 4
Issuesバグ報告・機能要望・タスク管理のチケット。ラベル・アサイン・マイルストーン・テンプレートが使えるSection 7
Pull Request(PR)ブランチ間の変更提案とコードレビュー。diff 表示・inline コメント・Approve・Merge が GUI で完結Section 6
ActionsYAML で定義する CI/CD パイプライン。push・PR イベントをトリガーに terraform plan を自動実行第5弾で詳述
Projects(V2)カンバンボード形式のタスク管理。Issues・PR と連携して進捗を可視化Section 7
Branches & Protectionブランチポリシー管理。PR レビュー必須・status check 必須などを強制Section 9
Security(Dependabot/Secret Scanning)依存パッケージの脆弱性自動検知・secrets の誤コミット検出とアラートSection 9 で概要のみ
Discussionsフォーラム形式のコミュニティ議論スペース。Q&A・アナウンスに使える本シリーズでは使用しない
PackagesDocker イメージ・npm/pip パッケージの配布レジストリ本シリーズでは使用しない
Pagesgh-pages ブランチや docs/ フォルダから静的サイトをホスティング本シリーズでは使用しない
Codespacesブラウザ上で動作するクラウド開発環境(VS Code ベース)本シリーズでは使用しない

本シリーズで体験する GitHub ワークフローの全体像

本シリーズを通じて体験する GitHub を中心とした開発フローを整理します。

フェーズ作業内容使う GitHub 機能
準備(本記事)リポジトリを GitHub に公開・認証設定Repository・SSH key・PAT・GitHub CLI
日常開発(本記事)feature ブランチで変更→PR→レビュー→マージPull Request・Code Review
タスク管理(本記事)Issue で作業を管理・PR と自動連携Issues・Projects
品質管理(第3〜4弾)ブランチ保護・CODEOWNERS・pre-commitBranch Protection・Secret Scanning
自動化(第5弾)PR をトリガーに terraform plan を自動実行GitHub Actions・OIDC

このフローが整うと、「インフラ変更を手動でサーバーに適用する」作業から「PR をマージするだけで自動的にインフラが変わる」状態へ進化します。本記事はその第一歩です。


2-4. Terraform エコシステムにおける GitHub の位置付け

Terraform を使う実務エンジニアにとって、GitHub は単なるコード置き場ではありません。Terraform エコシステム全体が GitHub と深く統合されています。

公式モジュールの配布拠点

registry.terraform.io で公開されているモジュール(例: terraform-aws-modules/terraform-aws-vpc)は、すべて GitHub リポジトリとして管理されています。Terraform モジュールを source で参照する際に github.com/ 形式を使う場面も多く、バグ報告・機能要望・PR 提出の標準的な窓口が GitHub です。

# Terraform Registry 経由(標準方式)
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
}

# GitHub 直接参照(プライベートモジュール等)
module "internal_vpc" {
  source = "github.com/your-org/terraform-modules//vpc"
}

OIDC 連携による無パスワード認証(第5弾への布石)

第5弾「GitHub Actions × OIDC」では、GitHub Actions ワークフローが AWS に一時クレデンシャルを要求し、terraform planapply を自動実行する仕組みを構築します。OIDC(OpenID Connect)を使うと、AWS アクセスキーを GitHub Secrets に保存する必要がなく、セキュリティリスクを大幅に低減できます。

GitHub Actions ワークフロー
 ↓ JWT トークンを生成
AWS STS(IAM OIDC プロバイダ)
 ↓ トークン検証・一時クレデンシャル発行
terraform plan / apply を実行

この連携を実現するために、本記事で作成する GitHub リポジトリが起点となります。Section 9 で設定するブランチ保護ルールも、第5弾の CI/CD と組み合わせて「PR をマージしないと terraform apply が実行されない」という安全ガードレールを作る第一歩です。

Terraform コードのコラボレーション

Terraform の .tf ファイルはすべてテキストです。Git でバージョン管理し、GitHub でチームと共有することで、「誰がいつどのインフラ変更を行ったか」が完全に追跡可能になります。これが IaC(Infrastructure as Code) の本質的な価値です。

  • git log でインフラ変更の全履歴を参照できる
  • PR のレビューでインフラ変更の diff を事前確認できる(terraform plan 結果も PR に添付可能)
  • Issue で「なぜその変更が必要だったか」の背景を残せる

シリーズ全体における GitHub の位置付け

本シリーズ 5 弾の構成で、GitHub は各弾に横断的に関わります。

タイトルGitHub の役割
第1弾Git入門ローカル完結。GitHub は登場しない
第2弾(本記事)GitHub入門リポジトリホスティング・PR・Issue・CLI の習得
第3弾ブランチ戦略GitHub のブランチ保護ルールと GitFlow/trunk-based の実践場
第4弾セキュリティSecret Scanning・Dependabot・pre-commit フック の設定場
第5弾GitHub Actions × OIDCCI/CD パイプラインと OIDC で AWS を無パスワード認証

第2弾(本記事)を正しく完了することが、第3〜5弾に進む土台になります。


2-5. 無料プラン vs Team vs Enterprise の機能差

GitHub の料金プランは大きく 3 段階あります。本シリーズでは無料プラン(Free)で全ハンズオンが完結します。

機能Free(無料)Team($4/人/月)Enterprise($21/人/月)
パブリックリポジトリ無制限無制限無制限
プライベートリポジトリ無制限無制限無制限
コラボレーター数無制限無制限無制限
Actions 無料枠(月)2,000 分3,000 分50,000 分
Packages Storage500 MB2 GB50 GB
コードレビュー担当者の指定1 人複数人指定可複数人指定可
ブランチ保護(基本ルール)
Required status checks
Require PR review before merge✓(Free でも基本ルールは使える)
CODEOWNERS(自動レビュアー割当)
Secret scanning(パブリック Repo)
Secret scanning(プライベート Repo)
SAML SSO / SCIM
監査ログ最小限強化版完全版
GitHub Supportコミュニティのみ標準サポート優先サポート

学習者・個人開発者への推奨: Free プランで十分です。 本シリーズで扱うブランチ保護・Required status checks・Secret Scanning(パブリックリポジトリ)・Actions CI/CD はすべて Free プランの範囲内で動作します。

企業・チーム利用の判断基準: プライベートリポジトリでの Secret Scanning や SAML SSO による組織認証管理が必要になった場合に Team または Enterprise へ移行を検討します。Terraform を本番 AWS 環境で運用する場合は、セキュリティ要件から Team 以上を採用するケースが多いです。

GitHub Education について: 学生・教員向けの「GitHub Education」プログラムでは、通常は有料の機能(GitHub Copilot など)が無料で利用できます。大学・高専の学籍メールアドレスを持っている場合は education.github.com から申請してみてください。


Section 3: GitHubアカウント + 認証設定ハンズオン

3-1. GitHub アカウント作成と 2 段階認証の設定

アカウントを既にお持ちの方はこの手順をスキップして 3-2 へ進んでください。

GitHub アカウントは github.com から無料で作成できます。2024 年以降、GitHub はすべてのアカウントに対して 2 段階認証(2FA: Two-Factor Authentication)の設定を義務付けています。アカウント作成後は必ず設定してください。

Section 3 で設定する認証の全体像

Section 3 を通じて次の 3 つの認証方式を順番に設定します。完了後には GitHub への接続手段が 3 つ揃い、あらゆる場面に対応できます。

順番Section認証方式用途難易度
3-3SSH key(ed25519)git pushgit pull などの Git 操作★★☆
3-4PAT(Fine-grained token)GitHub API・スクリプト自動化★☆☆
3-6GitHub CLI(gh)PR・Issue・リポジトリ作成の CLI 操作★☆☆

アカウント作成の手順

  1. github.com にアクセスし、画面右上の「Sign up」ボタンをクリックする
  2. メールアドレス・パスワード・ユーザー名を入力してアカウントを作成する
  3. ユーザー名は GitHub 上の URL に使われる(例: github.com/your-username)。公開されるため慎重に選ぶ
  4. ユーザー名に個人情報(本名・生年月日・電話番号など)を含めないことを推奨する
  5. 一度設定したユーザー名は後から変更可能だが、既存のリポジトリ URL が変わるため注意
  6. 人間チェック(CAPTCHA)を完了する
  7. メールアドレス確認のメールが届くので、メール内のリンクをクリックして認証する

2 段階認証(2FA)の設定

2FA を設定することで、パスワードが漏洩しても第三者がアカウントにアクセスできなくなります。

  1. 画面右上のプロフィールアイコンをクリックし、「Settings」を選択する
  2. 左サイドバーの「Password and authentication」をクリックする
  3. 「Two-factor authentication」セクションまでスクロールし、「Enable two-factor authentication」をクリックする
  4. 「Set up using an app」(認証アプリを使う方式)を選択する
  5. SMS 認証(電話番号)は推奨しない: SIM スワッピング攻撃によってアカウントを乗っ取られるリスクがある
  6. 推奨する認証アプリ: Google Authenticator・Authy・1Password・Microsoft Authenticator など
  7. 表示された QR コードを認証アプリでスキャンする
  8. 認証アプリに表示された 6 桁のワンタイムコードを入力して確認する
  9. リカバリーコードを必ずダウンロードして安全な場所に保管する
  10. デバイスを紛失・故障した場合に、認証アプリが使えない状態でもアカウント復旧に使える唯一の手段
  11. パスワードマネージャー(1Password・Bitwarden・KeePass など)に保存するか、プリントアウトして金庫に保管することを強く推奨する
  12. リカバリーコードを紛失すると、サポートへの問い合わせが必要になり、アカウントへのアクセスを失うリスクがある

3-2. 認証方式の選択 — SSH key vs PAT vs GitHub CLI

GitHub へのアクセスには主に 3 つの認証方式があります。用途と使い分けを理解してから設定を進めましょう。

認証方式仕組み主な用途強み弱み
SSH key公開鍵暗号。ローカルに秘密鍵、GitHub に公開鍵を登録。git@github.com: URL で使用git pushgit pull など Git 操作全般一度設定すればパスワード不要・高セキュリティデバイスごとに鍵を登録する必要がある
PAT(Personal Access Token)ランダム文字列のトークン。HTTPS URL の Basic 認証パスワード代わりまたは API ヘッダーで使用API アクセス・スクリプト自動化・HTTPS clone権限スコープを細かく限定できる管理が煩雑。漏洩時のリスクがある
GitHub CLI(gh)OAuth フローでブラウザ経由認証。内部でトークンを自動管理gh コマンドによる PR・Issue・リポジトリ操作ブラウザ認証で簡単・CLI 操作が効率化されるgit コマンドのリモート操作には直接使えない

認証方式の使い分け指針

git push / git pull → SSH key(メイン認証)
GitHub API 呼び出し → PAT(スクリプト・CI/CD)
gh pr create / gh repo create → GitHub CLI(gh)

本記事での方針: 3 方式すべてを設定します。

  • git pushgit pull には SSH key を使用(Section 4〜5 のハンズオン主力)
  • GitHub API の動作確認に PAT を使用
  • PR・Issue 操作・リポジトリ作成に GitHub CLI を使用

3 方式を使い分けることで、実務で遭遇するあらゆる状況に対応できます。

認証方式ごとのセキュリティリスクと管理コスト

認証方式を選ぶ際には、セキュリティリスクと管理コストのトレードオフを理解することが重要です。

観点SSH keyPATGitHub CLI
漏洩リスク低(秘密鍵はローカルに保管・パスフレーズで保護)中(トークン文字列が漏洩すると即悪用可能)低(ブラウザ OAuth で発行・ファイルに保存)
ローテーション頻度低(デバイス紛失時のみ)高(有効期限ごとに更新)低(OAuth トークンは自動更新)
複数デバイス対応デバイスごとに鍵ペアを作成して登録単一トークンを複数場所で使い回し可(非推奨)・デバイスごとに別トークン推奨デバイスごとに gh auth login を実行
取り消し方法GitHub 設定から公開鍵を削除GitHub 設定からトークンを削除GitHub 設定から OAuth アプリを取り消し

3-3. [ハンズオン] SSH key 生成と GitHub への登録

SSH key を使った認証は、パスワードを毎回入力せずに git pushgit pull を安全に行う最も推奨される方法です。SSH key は公開鍵(.pub ファイル)秘密鍵(.pub なし)のペアで機能します。GitHub に登録するのは公開鍵のみです。秘密鍵は絶対に外部に送らないでください。

STEP 1: 既存 SSH key の確認

まず、既に SSH key が存在するか確認します。

ls -la ~/.ssh/

id_ed25519(秘密鍵)と id_ed25519.pub(公開鍵)がすでに存在する場合は、既存の鍵を GitHub に登録するだけで構いません(STEP 4 へジャンプ)。

ファイルが存在しない場合または古い id_rsa しかない場合は、STEP 2 へ進んで新しい鍵を生成してください。

STEP 2: ed25519 アルゴリズムで SSH key を生成

古い RSA(2048bit)より安全で処理も速い ed25519 アルゴリズムを推奨します。-C オプションで GitHub に登録したメールアドレスを識別コメントとして追加します。

ssh-keygen -t ed25519 -C "your_email@example.com"

実行すると対話式の質問が表示されます。以下に各質問の回答指針を示します。

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):

→ Enter キーを押して既定のパス(~/.ssh/id_ed25519)を使用します。すでに同名のファイルがある場合は別のファイル名を指定してください(例: ~/.ssh/id_ed25519_github)。

Enter passphrase (empty for no passphrase):
Enter same passphrase again:

パスフレーズの設定を強く推奨します。 秘密鍵ファイルが漏洩した場合の第2の防壁となります。毎回の入力が煩わしい場合は、後述の Keychain 登録(macOS)または ssh-agent(Linux)で自動化できます。

成功すると次のメッセージが表示されます。

Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcd your_email@example.com
The key's randomart image is:
...(省略)...

STEP 3: 公開鍵の内容を確認してクリップボードにコピー

cat ~/.ssh/id_ed25519.pub

次のような形式の文字列が表示されます。

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicKeyStringHerexxxxxxxxxxxxxx your_email@example.com

この文字列全体をコピーします(ssh-ed25519 から メールアドレスの末尾まで、改行は含めない)。

クリップボードへの自動コピーコマンド:

# macOS
cat ~/.ssh/id_ed25519.pub | pbcopy

# Ubuntu(xclip がインストールされている場合)
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard

# Ubuntu(xsel がインストールされている場合)
cat ~/.ssh/id_ed25519.pub | xsel --clipboard --input

STEP 4: GitHub に公開鍵を登録

  1. GitHub の右上プロフィールアイコン → 「Settings」をクリックする
  2. 左サイドバーの「SSH and GPG keys」をクリックする
  3. 右上の「New SSH key」ボタンをクリックする
  4. 各フィールドを次のように入力する
フィールド入力値説明
TitleMacBook Pro 2024 などどのデバイスの鍵か識別できる名前。複数デバイスを使う場合に管理しやすくなる
Key typeAuthentication Keyコミット署名には「Signing Key」を選ぶが、通常は Authentication Key
KeySTEP 3 でコピーした公開鍵ssh-ed25519 AAAA... から始まる文字列全体
  1. 「Add SSH key」をクリックして保存する
  2. 確認のためにパスワード(または 2FA コード)の入力を求められる場合は入力する

STEP 5: SSH 接続テスト

ssh -T git@github.com

初回接続時は GitHub サーバーのホストキーを確認するメッセージが表示されます。

The authenticity of host 'github.com (140.82.121.4)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.

yes を入力してください(これは正常な動作です。フィンガープリントが上記と異なる場合は接続を中止してください)。

認証成功時のメッセージ:

Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.

your-username がご自身の GitHub ユーザー名に置き換わっていれば SSH 認証の設定は完了です。

macOS でのパスフレーズ自動化(Keychain 登録)

パスフレーズを設定した場合、git push のたびに入力が必要になります。macOS の Keychain にパスフレーズを保存することで、以後の入力を省略できます。

# ssh-agent にパスフレーズを登録(macOS Keychain 連携)
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

さらに ~/.ssh/config ファイルに次の設定を追加すると、ターミナルを開き直しても自動で鍵が読み込まれます。

Host github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Linux での ssh-agent 自動起動

Ubuntu など Linux 環境では、ssh-agent を明示的に起動して鍵を追加する必要があります。~/.bashrc または ~/.zshrc に次の設定を追加します。

# ~/.bashrc または ~/.zshrc に追記
if [ -z "$SSH_AUTH_SOCK" ]; then
  eval "$(ssh-agent -s)"
  ssh-add ~/.ssh/id_ed25519
fi

この設定により、新しいターミナルセッションを開くたびに ssh-agent が起動し、鍵が自動的に登録されます。

SSH 接続が失敗する場合のトラブルシューティング

エラーメッセージ原因対処法
Permission denied (publickey)公開鍵が GitHub に登録されていない、または秘密鍵が見つからないssh-add -l で鍵を確認。ssh -vT git@github.com で詳細ログを見る
ssh: connect to host github.com port 22: Connection refused社内ネットワーク・ファイアウォールで 22 番ポートがブロックされているHTTPS ポート(443)経由の SSH を使う。~/.ssh/configHostname ssh.github.com + Port 443 を設定
WARNING: UNPROTECTED PRIVATE KEY FILE!秘密鍵ファイルのパーミッションが広すぎるchmod 600 ~/.ssh/id_ed25519 でパーミッションを修正する
Host key verification failedknown_hosts に古いエントリが残っているssh-keygen -R github.com で古いエントリを削除してから再接続

3-4. [ハンズオン] PAT(Fine-grained Token)の発行 — 最小権限の原則

PAT(Personal Access Token)は、GitHub API へのアクセスやスクリプト自動化に使うトークンです。2022 年に導入された Fine-grained token では、アクセス対象リポジトリと権限スコープを細かく限定でき、従来の「Classic token」より安全です。

Classic token と Fine-grained token の比較

比較軸Classic tokenFine-grained token
リポジトリ範囲アカウント全リポジトリ特定リポジトリのみ指定可
権限粒度大まかなスコープ(repo/user/workflow など)機能単位で細かく制御(Contents/Issues/PR/Actions など各権限ごとに Read/Write/None)
有効期限期限なし設定可(非推奨)必ず有効期限を設定(最大 366 日)
推奨度レガシー(新規作成は避ける)現在の推奨方式

最小権限の原則(Principle of Least Privilege): アクセス権限は、その操作に必要な最小限のスコープのみ付与します。万が一 token が漏洩した場合の被害範囲を最小化するため、不要な権限は絶対に付与しないでください。

STEP 1: Fine-grained PAT の発行手順

  1. GitHub の右上プロフィールアイコン → 「Settings」をクリックする
  2. 左サイドバー最下部の「Developer settings」をクリックする
  3. 「Personal access tokens」→「Fine-grained tokens」を選択する
  4. 「Generate new token」ボタンをクリックする
  5. 以下の設定を入力する
設定項目入力値理由
Token nameterraform-git-handson-read用途を明示した分かりやすい名前にする
Expiration30 days短い有効期限でリスクを低減。期限なしは設定不可(Fine-grained の特徴)
Description第2弾ハンズオン用 読み取り専用トークン後で見返した時に用途が分かる説明
Resource owner自分のユーザー名Organization リポジトリには使わない
Repository accessOnly select repositories → terraform-git-handson対象リポジトリを限定する(他のリポジトリへのアクセスを禁止)
  1. 「Repository permissions」で以下のスコープのみ許可する(それ以外はすべて No access のまま)
権限設定値理由
ContentsRead-onlyリポジトリ内容(ファイル・コミット)の読み取り
MetadataRead-onlyリポジトリ情報の取得(自動付与・変更不可)

Write 権限・Delete 権限は絶対に付与しないことが重要です。本ハンズオンでは API 経由での書き込みは行いません。

  1. 「Generate token」をクリックすると github_pat_xxxxx... 形式のトークンが画面に表示される
  2. この画面を閉じると二度と同じトークンが表示されない。 パスワードマネージャー(1Password・Bitwarden など)に直ちに保存する

STEP 2: PAT の動作確認

# TOKEN 変数に取得した PAT を設定(以下はダミー値。実際のトークンに置き換えること)
TOKEN="github_pat_xxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# GitHub API でユーザー情報を取得して PAT の有効性を確認
curl -s \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/user | grep '"login"'

"login": "your-username", が含まれるレスポンスが返れば認証成功です。

セキュリティ注意事項:
TOKEN 変数はターミナルのセッション変数に一時保存しているだけです。~/.bashrc~/.zshrc に直接書かないでください
– スクリプトで PAT を使う場合は、.env ファイルに書いて .gitignore で除外するか、CI/CD の Secrets 機能を使って環境変数として外部から渡す方式を採用してください


3-5. PAT 漏洩時の即時ローテーション手順

⚠️ PAT が漏洩した場合の即時対応手順

PAT をコードに直接書き込んで誤って git push してしまった場合、GitHub の Secret Scanning が自動検出して無効化しますが、検出には数分かかる場合があり、その間にアクセスされるリスクがゼロではありません。漏洩に気づいたら即座に対応してください。

STEP 1: 漏洩したトークンを即座に無効化する(最優先)

1. GitHub の「Settings」→「Developer settings」→「Fine-grained tokens」を開く
2. 該当トークンの右側にある「Delete」ボタンをクリックして即時無効化する
3. 「Token deleted」が表示されたことを確認する(これ以降、そのトークンは一切使えなくなる)

STEP 2: 新しいトークンを発行する

Section 3-4 の手順で新しいトークンを発行し、そのトークンを使用していたスクリプト・サービス・ドキュメントをすべて更新する。

STEP 3: コミット履歴にトークンが残っていないか確認する

git log --all -p | grep "github_pat_"

コミット履歴にトークンが含まれていた場合は、リポジトリを即座に Private に変更したうえで、git filter-repo または BFG Repo-Cleaner を使って履歴から削除する。すでに Public リポジトリとして公開していた場合は、削除するだけでは追跡エンジンにキャッシュされている可能性があるため、GitHub サポートに報告する。

STEP 4: アクセスログで不審なアクセスを確認する

GitHub の「Settings」→「Security log」でトークンを使ったアクセス履歴を確認し、不審な IP アドレスや操作がないか検証する。

PAT 漏洩の予防策

.gitignore.env*.pem*token**secret* を追加する(第1弾で設定済みの .gitignore はすでに Terraform 関連を除外しているので確認する)
– PAT を含むファイルは絶対にコミットしない
git diff --staged でコミット前に diff を目視確認する習慣をつける
– pre-commit フック(第4弾で詳述)で秘密情報の混入を自動検出する仕組みを使う


3-6. [ハンズオン] GitHub CLI(gh)のインストールと認証

GitHub CLI(gh)は、GitHub のほぼすべての操作をターミナルから実行できる公式 CLI ツールです。PR の作成・マージ・レビュー、Issue の起票・クローズ、リポジトリの作成、ワークフローの実行管理などが gh コマンド一本で完結します。

STEP 1: インストール

# macOS(Homebrew が必要。未インストールの場合は brew.sh 参照)
brew install gh

# Ubuntu / Debian(apt でインストール)
sudo apt update && sudo apt install gh -y

# バージョン確認
gh --version

期待される出力例(バージョン番号は異なる場合があります):

gh version 2.49.2 (2024-10-15)
https://github.com/cli/cli/releases/tag/v2.49.2

gh v2.40 以上であれば本記事の全コマンドが動作します。

STEP 2: gh auth login でブラウザ認証

gh auth login

対話式のメニューが順番に表示されます。各質問に答えていきます。

? What account do you want to log into?
> GitHub.com
  GitHub Enterprise Server

? What is your preferred protocol for Git operations on this host?
  HTTPS
> SSH

? Upload your SSH public key to your GitHub account?
> ~/.ssh/id_ed25519.pub
  Skip

? How would you like to authenticate GitHub CLI?
> Login with a web browser
  Paste an authentication token

本記事では:
– GitHub.com を選択
– プロトコルは SSH(Section 3-3 で設定済みの SSH key を使用)
– SSH 公開鍵をアップロードするオプションが表示された場合は ~/.ssh/id_ed25519.pub を選択(Section 3-3 でアップロード済みの場合はスキップ)
– 認証方式は「Login with a web browser」を選択

! First copy your one-time code: ABCD-1234
Press Enter to open github.com in your browser...
  1. ターミナルに表示された one-time codeXXXX-XXXX 形式 8 桁)をメモまたはコピーする
  2. Enter キーを押す(ブラウザが自動で https://github.com/login/device を開く)
  3. GitHub にログインしている状態でそのページに one-time code を貼り付けて「Continue」をクリックする
  4. GitHub CLI が要求する権限(reporead:org など)を確認して「Authorize GitHub CLI」をクリックする
  5. ターミナルに戻ると認証完了のメッセージが表示される

STEP 3: 認証状態の確認

gh auth status

正常に認証されている場合の出力:

github.com
  ✓ Logged in to github.com account your-username (/Users/user/.config/gh/hosts.yml)
  - Active account: true
  - Git operations protocol: ssh
  - Token: gho_****
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

Logged in to github.com account your-username が表示されれば GitHub CLI の認証完了です。


3-7. 認証動作確認まとめ — 3 方式の横断チェックリスト

Section 3-3・3-4・3-6 で設定した 3 つの認証方式が正しく動作しているかをまとめて確認します。以下のコマンドをすべて実行し、期待する出力が得られることを確認してください。

SSH key の動作確認

# GitHub との SSH 接続テスト(先頭 Hi の後に自分のユーザー名が表示されることを確認)
ssh -T git@github.com

# ssh-agent に鍵が登録されているか確認(ED25519 と表示されることを確認)
ssh-add -l

期待する出力:
ssh -T git@github.comHi your-username! You've successfully authenticated, but GitHub does not provide shell access.
ssh-add -l256 SHA256:xxxxx your_email@example.com (ED25519)

PAT の動作確認

# TOKEN に自分の PAT を設定(以下はダミー値。実際のトークンに置き換えること)
TOKEN="github_pat_xxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# ユーザー情報を取得して自分のログイン名が返ることを確認
curl -s \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.github+json" \
  https://api.github.com/user | python3 -m json.tool | grep '"login"'

期待する出力: "login": "your-username",

GitHub CLI の動作確認

# 自分のリポジトリ一覧を表示(GitHub 上のリポジトリが一覧表示されることを確認)
gh repo list --limit 5

# gh API 経由で自分のログイン名を取得(jq が不要な形式で確認)
gh api user --jq '.login'

期待する出力: ご自身のリポジトリ名の一覧、および your-username

チェックリスト

本セクションを完了したら、以下の全項目にチェックを入れてください。

認証方式確認コマンド期待結果状態
SSH keyssh -T git@github.comHi your-username! が表示される[ ]
SSH key(パスフレーズ自動化)ssh-add -lED25519 の鍵が表示される[ ]
PAT(Fine-grained token)curl + /api/user"login": "your-username" が含まれる[ ]
GitHub CLIgh auth statusLogged in to github.com が表示される[ ]
GitHub CLI(API 確認)gh api user --jq '.login'ユーザー名が返る[ ]

全項目にチェックが入ったら、Section 4「リモートリポジトリ作成 + 初回 push ハンズオン」へ進みましょう。


Section 3 まとめ — 認証設定の振り返り

Section 3 では GitHub への接続に必要な 3 つの認証方式をすべて設定しました。以下の表で、それぞれの方式がどのコマンドや操作と紐付いているかを確認してください。

認証方式設定したもの使うシーン確認コマンド
SSH key(ed25519)~/.ssh/id_ed25519(秘密鍵)+ GitHub に公開鍵登録git clone git@github.com:...git pushgit pullssh -T git@github.com
PAT(Fine-grained token)github_pat_... トークンをパスワードマネージャーに保存curl での GitHub API 呼び出し・スクリプト自動化curl -H "Authorization: Bearer TOKEN" /api/user
GitHub CLI(gh)gh auth login で OAuth トークンを ~/.config/gh/ に保存gh repo creategh pr creategh issue list などgh auth status

各方式の使い分けフロー

git コマンドでリモート操作する
 → SSH key を使う(git@github.com: URL で clone/push/pull)

GitHub API を直接呼ぶ(curl / スクリプト)
 → PAT を使う(Bearer Token として Authorization ヘッダーに設定)

gh コマンドで PR・Issue・リポジトリを操作する
 → GitHub CLI(gh)を使う(認証は自動管理)

Section 3 で学んだセキュリティ原則

  • 最小権限: PAT は必要最小限のスコープ(今回は Contents: Read-only のみ)で発行する
  • 有効期限: PAT には必ず有効期限を設定する(Fine-grained token は期限なし設定が不可)
  • 2FA 必須: GitHub アカウントには認証アプリによる 2 段階認証を設定する
  • 秘密鍵の保護: SSH 秘密鍵はパーミッション 600 で保管し、外部に送らない
  • 漏洩時の即時無効化: PAT が漏洩したら Section 3-5 の手順で即座に対処する

次のセクションに向けての準備確認

Section 4 でリモートリポジトリを作成する前に、次の状態になっていることを最終確認してください。

確認項目方法
SSH key が GitHub に登録されているssh -T git@github.comHi username! が表示される
terraform-git-handson/ がローカルに存在するls terraform-git-handson/main.tf でファイルが確認できる
gh コマンドが認証済みであるgh auth statusLogged in が表示される
git の user.name と user.email が設定されているgit config --global user.namegit config --global user.email で値が表示される

git config が未設定の場合は次のコマンドで設定してください(第1弾 Section 3 で設定済みのはず)。

git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"

これらが揃ったら、いよいよ terraform-git-handson/ を GitHub にプッシュする Section 4 へ進みましょう。


Section 4: リモートリポジトリ作成と初回 push ハンズオン

Section 3 で SSH key・PAT・GitHub CLI の認証基盤を整えました。いよいよ第1弾で作成した terraform-git-handson/ をGitHub に公開し、チームや CI/CD から参照できる状態にします。このセクションでは「GitHub でリポジトリを作る → ローカルに繋ぐ → 初回 push」という一連の流れを、GUI と CLI の両方から体験します。

4-1. Public vs Private の選択基準

GitHub リポジトリを作成するとき、最初に決める設定が Public(公開)Private(非公開) かです。以下のテーブルで特徴を整理します。

観点PublicPrivate
閲覧権限インターネット上の全員が読める招待されたメンバーのみ
コントリビューション誰でも fork → PR が送れる招待メンバーのみ
Actions 無料枠月 2,000 分(無料プラン)月 2,000 分(無料プラン)※
GitHub Pages無料で公開できる有料プランのみ(Team 以上)
オープンソース最適不向き
IaC(Terraform)コード⚠️ 原則 Private を推奨推奨 ✅

※ 2025 年現在の無料プラン上限。最新情報は GitHub 公式ドキュメントを確認してください。

Terraform IaC は原則 Private にする理由

Terraform コードには次のような情報が含まれやすく、公開リポジトリに誤って push すると深刻なセキュリティインシデントになります。

  • terraform.tfvars*.auto.tfvars に書いた AWS アカウント ID・リソース名
  • backend.tf に書いた S3 バケット名・DynamoDB テーブル名
  • terraform.tfstate に含まれるリソースの実 ARN・IP アドレス

Private に設定し、機密ファイルを .gitignore で除外する のが Terraform IaC 管理の基本です。


4-2. GitHub.com でリポジトリを作成する(GUI 手順)

GitHub のウェブ UI からリポジトリを作成する手順です。後の 4-3 で CLI から同等操作を行うので、どちらか一方だけ実行してください。

手順

  1. https://github.com/new にアクセスする
  2. Repository nameterraform-git-handson を入力する
  3. DescriptionTerraform IaC hands-on — Git/GitHub 実践シリーズ などを記入する(任意)
  4. Private を選択する(IaC コードのため)
  5. Add a README fileチェックしない(ローカルに既にコミットがあるため、初期化すると push 時に履歴が競合する)
  6. Add .gitignoreNone のまま(第1弾で作成済み)
  7. Choose a licenseNone のまま(Private リポジトリのため省略)
  8. Create repository ボタンをクリックする

なぜ README 初期化しないのか?
GitHub 側で README を作成すると「GitHub 上にコミットが存在する状態」になります。ローカルにも既にコミット履歴がある場合、git push 時に「リモートにローカルにない履歴がある」と判断され non-fast-forward エラーが発生します。ローカルのコミット履歴をそのまま GitHub に送り込みたい場合は、空のリポジトリとして作成するのが正解です。


4-3. gh コマンドでリポジトリを作成する(CLI 手順)

Section 3-6 で設定した gh コマンドを使うと、ターミナルを離れずにリポジトリを作成できます。4-2 の GUI 操作と同じリポジトリを CLI で作る例です(4-2 を実行済みの場合はスキップ)。

# Private リポジトリを作成(--source で既存ディレクトリと紐付け)
gh repo create terraform-git-handson \
  --private \
  --description "Terraform IaC hands-on — Git/GitHub 実践シリーズ"

# 作成結果を確認
gh repo view terraform-git-handson

gh repo create の主要オプション一覧:

オプション説明
--privatePrivate リポジトリとして作成
--publicPublic リポジトリとして作成
--description "..."リポジトリの説明文を設定
--clone作成後に自動的に git clone も実行
--source .カレントディレクトリを既存ローカルリポとして登録

gh repo create と GUI の使い分け
チームの CI/CD スクリプトやドキュメントに「リポジトリ作成手順」を載せる場合は CLI の方が再現性が高く、スクリプト化もしやすいです。一方で組織ポリシー(Organization のテンプレートリポジトリ適用など)が必要な場合は GUI の方が確実です。


4-4. git remote add origin でリモートを登録する

GitHub 上にリポジトリを作成した直後は、ローカルリポジトリはまだそのリモート URL を知らない 状態です。git remote add origin でリモート URL を登録します。

# terraform-git-handson/ ディレクトリに移動
cd terraform-git-handson

# リモート URL を origin という名前で登録(SSH URL を使用)
git remote add origin git@github.com:YOUR_USERNAME/terraform-git-handson.git

# 登録内容を確認(fetch と push の URL が表示される)
git remote -v

実行結果の例:

origin  git@github.com:YOUR_USERNAME/terraform-git-handson.git (fetch)
origin  git@github.com:YOUR_USERNAME/terraform-git-handson.git (push)

origin という名前について

origin はリモートリポジトリに付けるエイリアス(別名)です。技術的には任意の名前を使えますが、Git の慣例として「メインのリモート」には origin を使います。複数のリモートを管理する場合(Section 5-7 で解説)は upstream など別名を追加します。

SSH URL vs HTTPS URL

項目SSH URLHTTPS URL
形式git@github.com:USER/REPO.githttps://github.com/USER/REPO.git
認証SSH key(Section 3-3 で設定済み)PAT またはパスワード
push 時の入力不要(SSH agent が自動処理)毎回またはキャッシュが必要
推奨場面開発マシン(SSH key 管理可能な環境)CI/CD・Docker 内など(HTTPS + PAT の方がシンプル)

Section 3-3 で SSH key を設定しているため、ここでは SSH URL を使います。


4-5. git push -u origin main で初回プッシュ

リモートを登録したら、ローカルのコミット履歴を GitHub に送信します。

# 初回プッシュ(-u で追跡ブランチを設定する)
git push -u origin main

# トラッキングの確認([origin/main] と表示されれば成功)
git branch -vv

git branch -vv の実行結果例:

* main  a1b2c3d [origin/main] feat: add VPC module with public/private subnets

-u--set-upstream)フラグの意味

-u を付けると、ローカルの main ブランチが origin/main(リモート追跡ブランチ)を「上流(upstream)」として記憶します。これ以降は git pushgit pull を引数なしで実行できます。

コマンド-u 設定前-u 設定後
git pushfatal: The current branch main has no upstream branch エラーorigin main へ自動送信
git pullfatal: ... エラーorigin main から自動取得
git statusリモートとの差分表示なしYour branch is up to date with 'origin/main'. など差分表示

2回目以降のプッシュは git push だけで OK です。


4-6. GitHub UI でコミット履歴を確認する

プッシュが成功したら、ブラウザで GitHub を開いてコミット履歴を確認します。第1弾で積み上げたコミットが GitHub 上でも可視化されているはずです。

# ブラウザでリポジトリを開く(gh コマンドで直接開ける)
gh repo view --web

# ローカルのコミット履歴を確認(GitHub 上の表示と照合用)
git log --oneline -10

GitHub UI で確認できる主な情報:

確認項目場所
コミット一覧リポジトリトップ → Commits(コミット数のリンク)
各コミットの差分コミット一覧 → 任意のコミット SHA をクリック
ブランチ一覧リポジトリトップ → Branches タブ
ネットワークグラフInsights タブ → Network
コードの時点別表示コミット一覧 → <> アイコン(Browse the repository at this point)

第1弾のコミット内容が GitHub で可視化される価値

git log --oneline でローカルに表示されていたコミット(feat: add VPC modulerefactor: separate variables など)が、GitHub 上で 誰がいつどんな変更をしたか として記録されます。チームメンバーはこの履歴を見て、コードの変遷を追跡できます。


4-7. README.md を整備してリポジトリの入口を作る

GitHub のリポジトリトップページには README.md の内容が自動的に表示されます。第1弾では最小限の README.md を作成しましたが、ここで実用的な内容に拡充します。

以下は Terraform IaC リポジトリ向けの README.md テンプレートです。

# terraform-git-handson

Terraform × Git/GitHub 実践シリーズのハンズオン用 IaC コードです。

## 前提条件

- Terraform >= 1.5
- AWS CLI >= 2.x(認証済み)
- Git >= 2.39

## 使い方

```bash
# 初期化
terraform init

# 実行計画の確認
terraform plan

# リソースの作成
terraform apply

ディレクトリ構成

terraform-git-handson/
├── main.tf # プロバイダー設定・VPC モジュール呼び出し
├── variables.tf  # 入力変数定義
├── outputs.tf # 出力値定義
├── terraform.tfvars # 変数値(.gitignore で除外)
└── modules/
 └── vpc/# VPC サブモジュール

注意事項

  • terraform.tfvars.gitignore で除外されています
  • AWS リソースを作成すると費用が発生します。terraform destroy で必ず後片付けをしてください
README を更新したら、変更をコミットして push します。

```bash
# README の変更をステージング・コミット・プッシュ
git add README.md
git commit -m "docs: enhance README with prerequisites and usage"
git push

git push のみで origin main へ送信できるのは、4-5 で -u オプションを付けた効果です。


4-8. リポジトリテンプレート機能(応用)

同じ構成のリポジトリを複数のプロジェクトで繰り返し作成する場合、Template Repository(テンプレートリポジトリ) として登録しておくと便利です。

テンプレートとして登録すると、GitHub UI の「Use this template」ボタンから新しいリポジトリを作成できます。コミット履歴はコピーされず、ファイル構成だけが新しいリポジトリに複製されます。

# gh コマンドでテンプレートリポジトリとして設定
gh repo edit terraform-git-handson --template

# テンプレート設定の確認
gh repo view terraform-git-handson --json isTemplate --jq '.isTemplate'

Terraform 実務での使い方例:

ユースケーステンプレートに含めるもの
AWS プロジェクト標準構成providers.tfbackend.tf.gitignore.github/workflows/
モジュール開発用main.tfvariables.tfoutputs.tfexamples/
マルチ環境構成environments/dev/environments/prod/modules/

今回のハンズオンでは terraform-git-handson をテンプレート化する必要はありません。将来的に同種の IaC リポジトリを量産する際の参考として覚えておいてください。


Section 4 まとめ

やったことコマンド / 操作
GitHub でリポジトリ作成gh repo create --private または GUI
リモート URL を登録git remote add origin git@github.com:...
初回プッシュ + 追跡設定git push -u origin main
コミット履歴の確認gh repo view --web → Commits
README を整備して pushgit add README.md && git commit && git push

Section 5: push / pull / fetch の動作原理と実践

Section 4 でローカルリポジトリと GitHub リポジトリが繋がりました。次のステップは 双方向の同期です。チーム開発では自分が push した変更を他のメンバーが pull し、他のメンバーの変更を自分が pull するという操作が日常的に発生します。このセクションでは pushpullfetch の内部動作を理解し、よくある問題の対処法まで習得します。


5-1. リモート追跡ブランチの仕組み

Git のローカルリポジトリには、リモートの状態を「キャッシュ」として保持するリモート追跡ブランチが存在します。

# リモート追跡ブランチを含む全ブランチを表示
git branch -a

# リモートの詳細情報を確認(fetch/push URL、追跡状況)
git remote show origin

git branch -a の出力例:

* main
  remotes/origin/main

ローカルブランチとリモート追跡ブランチの関係

ブランチ種別名前の例実体
ローカルブランチmain.git/refs/heads/main
リモート追跡ブランチorigin/main.git/refs/remotes/origin/main
リモートの実ブランチmain(GitHub 上)GitHub サーバー上の参照

重要なのは origin/main は「最後に通信したときの GitHub の main の状態」 であり、リアルタイムに同期されているわけではない点です。GitHub 上で誰かが新しいコミットを push しても、git fetch を実行するまで origin/main は更新されません。

コマンドorigin/main の更新ローカル main の更新
git fetch✅ 更新される変更なし
git pull✅ 更新される✅ マージ(または rebase)される
git push✅ 更新される(push 成功時)変更なし

この理解が、次の fetch と pull の違いを正確に把握する鍵になります。


5-2. GitHub UI で変更を加えて fetch で差分を確認する

fetch と pull の違いを体験するために、GitHub の UI でファイルを直接編集して、ローカルに変更を取り込む操作をしてみます。

GitHub UI での編集手順(ブラウザ操作)

  1. gh repo view --web でリポジトリを開く
  2. README.md のファイル名をクリックする
  3. 右上の鉛筆アイコン(Edit this file)をクリックする
  4. 末尾に ## 更新履歴 などのセクションを追記する
  5. Commit changes ボタンをクリック → コミットメッセージを入力して保存する

これでリモート(GitHub 上)に新しいコミットが追加されました。ローカルはまだ古い状態です。

# git fetch でリモートの更新を取り込む(ローカル main には反映しない)
git fetch origin

# ローカル main とリモート origin/main の差分を確認
git status
git log --oneline origin/main ^main

git status の表示例:

On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

git log --oneline origin/main ^main は「origin/main にあって main にないコミット」を表示します。GitHub の UI で追加したコミットが表示されれば、fetch が正しく動作しています。

fetch のメリット

git pull は「取り込み + マージ」を一気に行いますが、git fetch は「確認だけ」です。「まずリモートの変更内容を見てから、マージするかどうか判断したい」というケースで使います。特に、リモートに予想外の大きな変更が入っている可能性があるときは、fetch で確認してから pull する習慣が安全です。


5-3. git pull の内部動作(fetch + merge の分解)

git pull は内部で git fetchgit merge(または git rebase)を順番に実行しています。この分解を理解しておくと、pull が失敗したときのトラブルシューティングが容易になります。

# 方法1: fetch + merge を手動で実行(git pull と同等)
git fetch origin
git merge origin/main

# 方法2: git pull で一括実行(上記と同じ結果)
git pull origin main

fast-forward マージの動作

5-2 でローカルに変更がない状態で git pull した場合、Git は fast-forward マージを行います。

状態マージ方式マージコミット
ローカルに新コミットなしfast-forward作成されない(ポインタを進めるだけ)
ローカルとリモート両方に新コミット3-way merge作成される(マージコミットが残る)
--rebase 指定時rebase作成されない(コミット履歴が直線になる)

fast-forward は「歴史の分岐がない」ケースで使われ、コミット履歴が直線的に保たれます。git log --oneline --graph で視覚的に確認できます。


5-4. pull.rebase 設定の使い分け

第1弾 Section 3-9 で pull.rebase の設定に触れましたが、ここで実践を踏まえて使い分けを整理します。

# rebase モードを有効にする(コミット履歴を直線に保つ)
git config --global pull.rebase true

# merge モードに戻す(デフォルト。マージコミットが残る)
git config --global pull.rebase false

# 現在の設定を確認
git config --global pull.rebase

merge vs rebase の特徴比較

観点merge(デフォルト)rebase
コミット履歴分岐・合流が残る(*| のグラフ)直線になる
マージコミット作成される作成されない
競合発生時競合を1回解消コミットごとに解消が必要な場合あり
履歴の可読性「いつマージしたか」が明確シンプルで見やすい
公開ブランチへの適用✅ 安全⚠️ 注意(force push が必要になる場合あり)

チームの判断基準

  • 個人・フィーチャーブランチ: rebase が好まれる(PR がシンプルになる)
  • 共有ブランチ(main など): merge が安全(履歴の書き換えが発生しない)
  • OSS プロジェクト: プロジェクトの CONTRIBUTING.md の指示に従う

チームで統一されていない場合は false(merge モード)を選択し、必要に応じて git rebase を明示的に実行するのが安全です。


5-5. git push –force-with-lease(安全な強制 push)

通常の git push は「リモートに自分のローカルにないコミットがある場合」に拒否されます(non-fast-forward エラー)。これは他の人の変更を上書きしないための保護です。

ただし、意図的に履歴を書き換えたい場面(git rebasegit commit --amend 後)では強制 push が必要です。このとき --force は危険です。

# ❌ 危険: 他の人が push した変更ごと上書きしてしまう可能性
# git push --force origin main

# ✅ 安全: リモートが「自分の知っている状態」のときのみ push を許可
git push --force-with-lease origin main

--force-with-lease の動作原理

状況--force--force-with-lease
リモートが fetch 時と同じ状態push 実行push 実行 ✅
他の人が新しいコミットを push していた上書き(危険⚠️)push を拒否(安全✅)

--force-with-lease は「自分が最後に fetch した時点のリモートの状態」と現在のリモートを比較します。差異があれば push を拒否するため、チームメンバーの変更を誤って消す事故を防げます

Destructive Operation Safety ルール(本プロジェクト): git push --force は禁止です。強制 push が必要な場面では必ず --force-with-lease を使用してください。


5-6. push 拒否時の典型的対処

push が拒否される主な原因と対処法を整理します。

パターン1: non-fast-forward エラー(最多)

# エラーメッセージ例
# ! [rejected]  main -> main (non-fast-forward)
# error: failed to push some refs to 'git@github.com:YOUR_USERNAME/terraform-git-handson.git'
# hint: Updates were rejected because the tip of your current branch is behind
# hint: its remote counterpart.

# 対処: まずリモートの変更を取り込んでから push
git pull --rebase origin main
git push origin main

git pull --rebase を使うと、リモートのコミットの上に自分のコミットが乗る形になり、マージコミットが作成されません。

パターン2: protected branch エラー

# エラーメッセージ例
# ! [remote rejected] main -> main (protected branch hook declined)
# error: failed to push some refs to '...'

このエラーは GitHub の Branch protection rules によるものです。main ブランチへの直接 push を禁止し、Pull Request 経由でのみ変更を受け入れる設定になっているリポジトリで発生します。

対処方法:

  1. フィーチャーブランチを作成して push する
  2. GitHub で Pull Request を作成する(Section 6 で詳解)
  3. レビュー・承認後にマージする
# フィーチャーブランチで作業して push(protected branch 回避)
git checkout -b feature/update-vpc-cidr
# ... 変更作業 ...
git add .
git commit -m "feat: update VPC CIDR to /24 for scalability"
git push -u origin feature/update-vpc-cidr
# → その後 GitHub で PR を作成

5-7. 複数リモート(origin / upstream)の管理

GitHub では fork(フォーク) という機能で他のユーザーのリポジトリをコピーして自分のアカウントに置けます。OSS へのコントリビューションや組織のリポジトリを改変する際に使います。

fork ワークフローでは「自分の fork(origin)」と「元のリポジトリ(upstream)」の2つのリモートを管理します。

# upstream(元のリポジトリ)をリモートとして追加
git remote add upstream git@github.com:ORIGINAL_OWNER/terraform-git-handson.git

# 全リモートを確認(origin と upstream が両方表示される)
git remote -v

git remote -v の出力例:

origin git@github.com:YOUR_USERNAME/terraform-git-handson.git (fetch)
origin git@github.com:YOUR_USERNAME/terraform-git-handson.git (push)
upstream  git@github.com:ORIGINAL_OWNER/terraform-git-handson.git (fetch)
upstream  git@github.com:ORIGINAL_OWNER/terraform-git-handson.git (push)

upstream からの最新変更を取り込む

# upstream の変更を fetch(ローカルには反映しない)
git fetch upstream

# upstream/main の変更をローカル main にマージ
git checkout main
git merge upstream/main

# 自分の fork(origin)を upstream に追いつかせる
git push origin main
リモート名指す先主な用途
origin自分の fork(GitHub)日常の push / pull
upstream元のリポジトリ(GitHub)最新の取り込み(fetch + merge)

fork ワークフローの全体像(PR 作成まで)は Section 8 で詳しく扱います。ここでは「複数のリモートを git remote で管理できる」という概念を押さえておいてください。


Section 5 まとめ

概念 / コマンド内容
リモート追跡ブランチ origin/mainローカルが保持する「リモートの最終既知状態」のキャッシュ
git fetchリモートの変更をキャッシュに取り込む(ローカルブランチは変更しない)
git pullgit fetch + git merge(または rebase)の合成
git push --force-with-lease安全な強制 push(他者の変更を誤って消さない)
non-fast-forward 対処git pull --rebase origin maingit push
protected branch 対処フィーチャーブランチ → PR ワークフローへ
git remote add upstream複数リモート管理(fork ワークフローの準備)

Section 4〜5 を終えて: 次のセクションに向けて

Section 4 と 5 で、ローカルと GitHub の双方向同期の基本を習得しました。

習得済みスキル活用場面
GitHub でリポジトリ作成(GUI/CLI)新プロジェクト立ち上げ時
git remote add + git push -uローカルリポジトリの GitHub 初回公開
git fetch + 差分確認pull 前の安全確認
git pull --rebaseチーム開発での競合最小化
git push --force-with-leaseリベース後の安全な強制 push
複数リモート管理OSS コントリビューション・fork ワークフローの準備

次の Section 6・7 では、GitHub の目玉機能である Pull Request(PR)Issue の連携を、Terraform IaC のレビューフロー を題材に実践します。「コード変更 → PR → レビュー → マージ」という実務的なコラボレーションワークフローを習得しましょう。

Section 6: Pull Request ハンズオン — feature ブランチから main への変更提案


6-1. Pull Request の概念と Git の「pull」との違い

Pull Request(PR)は「コードレビューの依頼」であり、git pull コマンドとは別物です。 初学者が最も混乱するポイントなので、最初に明確に区別しておきます。

用語コマンド / 操作何をするか
git pullターミナルコマンドリモートブランチの最新コミットをローカルに取り込む
Pull Request(PR)GitHub の Web 機能 / gh コマンド「このブランチの変更を別ブランチ(通常 main)にマージしてほしい」という依頼を作成する

git pull はローカル操作、Pull Request は GitHub 上でのコミュニケーション手段です。名前が似ているのは歴史的な経緯によるもので、意味は全く異なります。GitLab や Bitbucket では同じ概念を「Merge Request(MR)」と呼ぶため、MR の方が実態を正確に表しているとも言えます。

Pull Request が生まれた背景

Git 単体はコードの差分管理ツールです。チーム開発では「誰がどのコードを書いたか」「なぜその変更が必要か」「品質は担保されているか」を確認する場が必要でした。Pull Request はそのレビュープラットフォームとして GitHub が 2008 年に発明した機能で、現在ではほぼすべての現代的なソフトウェア開発チームの標準ワークフローとなっています。

Pull Request の価値

観点効果
品質担保レビュワーがバグ・セキュリティ問題・設計ミスを発見できる
知識共有コードを見る全員が変更内容を把握できる
変更の記録なぜその変更をしたかが PR の説明文として永続的に残る
CI 連携PR 作成をトリガーに自動テスト・terraform plan が実行できる
承認フロー「X 人以上の Approve がなければマージできない」というルールが設定できる

Pull Request の基本的な流れ

ステップ作業内容場所
1feature ブランチを作成して変更をコミットローカル(ターミナル)
2feature ブランチをリモートに pushターミナル → GitHub
3GitHub 上で Pull Request を作成(タイトル・説明を記述)GitHub.com / gh コマンド
4レビュワーがコードを確認しコメントを付けるGitHub.com
5修正が必要なら追加コミットを push(PR に自動反映)ターミナル → GitHub
6Approve を得てマージGitHub.com / gh コマンド
7feature ブランチを削除してクリーンアップターミナル / GitHub

6-2. ハンズオン — feature/add-s3-module ブランチで S3 モジュールを追加する

第1弾で作成した terraform-git-handson/ リポジトリに、新しい S3 モジュールを追加する変更を feature ブランチで行い、Pull Request を作成します。

まず、リポジトリのルートに移動し、main ブランチを最新状態にしてから feature ブランチを切ります。

cd terraform-git-handson

# main ブランチを最新状態にする
git switch main
git pull origin main

# feature ブランチを作成して切り替える(-c は create の意味)
git switch -c feature/add-s3-module

# S3 モジュール用のディレクトリを作成
mkdir -p modules/s3

git switch -c は「ブランチを作成して即座に切り替える」ワンライナーです。第1弾で使った git checkout -b と同義ですが、git switch は Git 2.23 以降で追加された新しいコマンドで、ブランチ操作に特化しているため可読性が高いです。


6-3. S3 モジュールのファイルを作成してコミット + push する

S3 モジュールを構成するファイルを modules/s3/ 内に作成します。第1弾で作った modules/vpc/ の隣に配置するイメージです。

# modules/s3/main.tf — S3 バケットの最小構成リソース定義
resource "aws_s3_bucket" "this" {
  bucket = var.bucket_name
  tags = {
 Name  = var.bucket_name
 Environment = var.environment
  }
}

resource "aws_s3_bucket_versioning" "this" {
  bucket = aws_s3_bucket.this.id
  versioning_configuration {
 status = "Enabled"
  }
}

variable "bucket_name" {
  description = "S3 バケット名(グローバルで一意である必要があります)"
  type  = string
}

variable "environment" {
  description = "環境名(例: dev, staging, prod)"
  type  = string
  default  = "dev"
}

output "bucket_id" {
  description = "作成された S3 バケットの ID"
  value = aws_s3_bucket.this.id
}

output "bucket_arn" {
  description = "作成された S3 バケットの ARN"
  value = aws_s3_bucket.this.arn
}

ファイルを保存したら、変更をステージングしてコミットし、feature ブランチを GitHub に push します。

# 変更をステージングしてコミット
git add modules/s3/
git commit -m "feat: add S3 module for static assets

- バケット名と環境名を変数で設定可能
- バージョニングをデフォルト有効化(データ消失リスク低減)
- bucket_id と bucket_arn を出力値として定義"

# feature ブランチを GitHub に push
# -u でリモートの同名ブランチに追跡設定(以降は git push のみで OK)
git push -u origin feature/add-s3-module

push に成功すると、ターミナルに GitHub の Pull Request 作成 URL が表示されます。

remote: Resolving deltas: done.
remote:
remote: Create a pull request for 'feature/add-s3-module' on GitHub by visiting:
remote:https://github.com/<your-username>/terraform-git-handson/pull/new/feature/add-s3-module
remote:

この URL にアクセスするか、次のセクションで gh コマンドから PR を作成します。


6-4. GUI で Pull Request を作成する

GitHub.com でリポジトリを開くと、push したばかりのブランチに対して 「Compare & pull request」 バナーが表示されます。このバナーをクリックするか、Pull requests タブ → New pull request から PR を作成できます。

PR の作成フォームで記入する項目

フィールド記入内容記入例
タイトルConventional Commits 形式で変更内容を一行でfeat: add S3 module for static assets
本文何を・なぜ・どうテストするかを記述下記テンプレート参照
Reviewersレビューを依頼する GitHub ユーザーチームメンバーのアカウント
Labels変更の種類を分類するラベルenhancementinfrastructure
Milestone対応するマイルストーン(リリース計画がある場合)v1.0.0

PR 本文の推奨テンプレート

PR 本文は What / Why / How to test の 3 セクションで構成すると、後からコードを読む人(未来の自分も含む)が変更の意図を理解しやすくなります。以下はテンプレートの例です。

## What(何を変更したか)
- `modules/s3/` に S3 バケットリソースの Terraform モジュールを追加した
- バケット名・環境名を変数化し、bucket_id / bucket_arn を出力値として公開
- バージョニングをデフォルト有効化(コスト意識のため Enabled 固定)

## Why(なぜ変更したか)
Issue #5「静的ファイル配信用 S3 バケットの IaC 化」に対応するため。
現状はコンソールで手動作成しており、環境間の設定差異が発生しやすい。

## How to test(テスト方法)
terraform init && terraform plan -var='bucket_name=myapp-static-dev' を実行し、
Plan: 2 to add, 0 to change, 0 to destroy. が出力されることを確認する。

## 注意事項
S3 バケット名はグローバルで一意のため、本番適用時は
{project}-{env}-{randomsuffix} の命名規則を統一すること。

テンプレートを .github/pull_request_template.md に置いておくと、PR 作成フォームに毎回自動で挿入されます。

PR テンプレートをリポジトリに設置する方法

  1. .github/pull_request_template.md を作成して上記の内容を記述する
  2. git add .github/pull_request_template.md && git commit && git push origin main で反映する
  3. 以降、新しい PR を作成するたびに本文欄にテンプレートが自動入力される

6-5. CLI で Pull Request を作成する — gh pr create

GitHub CLI(gh)を使うと、ブラウザを開かずにターミナルから PR を作成できます。Section 3 で gh auth login 済みであれば、以下のコマンドがそのまま動作します。

# --fill でコミットメッセージからタイトル・本文を自動補完して PR 作成
gh pr create --fill

# 作成した PR をブラウザで確認
gh pr view --web

# PR の詳細をターミナルに表示
gh pr view

# タイトル・本文・ラベル・レビュワーを明示的に指定する場合
gh pr create \
  --title "feat: add S3 module for static assets" \
  --body "$(cat .github/pull_request_template.md)" \
  --label "enhancement" \
  --reviewer alice,bob

gh pr create --fill は最もシンプルな選択肢です。Conventional Commits 形式でコミットしている場合、コミットメッセージがそのまま PR タイトル・本文に反映されるため、ほぼ追記なしで使えます。

gh で PR を操作する主要コマンド一覧

コマンド説明
gh pr create --fillPR を自動補完で作成
gh pr view現在のブランチの PR 詳細を表示
gh pr view --webPR をブラウザで開く
gh pr list自分のリポジトリの PR 一覧
gh pr checkout 42PR #42 のブランチをローカルにチェックアウト
gh pr diffPR の差分を表示
gh pr review --approvePR を Approve
gh pr review --request-changes -b "コメント"変更要求
gh pr merge --squashSquash マージで PR をマージ
gh pr close 42PR #42 をクローズ

6-6. Draft PR の活用 — WIP 中のレビュー保留

変更途中でフィードバックを早めにもらいたい、または「まだレビューしないで」と伝えたい場合は Draft Pull Request を使います。Draft PR は通常の PR と同じく差分・コメントが確認できますが、Merge ボタンがグレーアウトされ、誤マージを防止できます。

# Draft PR として作成(--draft フラグを付けるだけ)
gh pr create \
  --draft \
  --title "WIP: feat: add S3 module" \
  --body "作業中。バケットポリシーの設定を追加予定。レビュー前にフィードバックがあればお願いします。"

# レビュー準備が整ったら Draft を解除して通常の PR に昇格
gh pr ready

# GitHub.com からも操作可能
# PR 画面の「Still in progress? Convert to draft」/ 「Ready for review」ボタン

Draft PR をどう使うか

ユースケース活用例
長期実装の途中経過共有「まだ終わっていないが設計の方向性についてフィードバックほしい」
WIP 表示でのレビュー予約「CI が通ったら Ready にする」
ブランチ保護との連携Draft 状態では自動マージルールが適用されないため誤操作を防止
コードの早期発見差分を早く共有することで根本的な設計ミスを早期発見

Draft PR と通常 PR の比較

項目通常 PRDraft PR
Merge ボタンアクティブグレーアウト(マージ不可)
レビュー依頼の自動通知されるされない(明示的に依頼するまで)
CI の実行されるされる(Draft でも CI は動く)
コメントできるできる
Files changed の閲覧できるできる

Draft PR は「コードは見せるけど、まだレビュー判定はしないで」という状態です。CI が常に動いているため、Draft のうちに自動テストを通過させてから Ready にするフローが効率的です。


6-7. レビュー依頼・Request changes・Approve のフロー

PR を作成したら、Reviewers に指定したメンバーへレビューの場が提供されます。レビュープロセスの状態遷移を理解しておきましょう。

PR のレビュー状態遷移

状態意味
Review requestedレビュー依頼済み・未対応
Commentedコメントのみ(承認でも変更要求でもない)
Changes requested変更要求あり・修正が必要
Approved承認済み
Dismissed承認が取り消された(コードが変更されたため)

レビュワーがコメントを付ける方法

GitHub.com の PR 画面で「Files changed」タブを開くと、行ごとにコメントを付けられます。コメントを書いた後に「Review changes」ボタンから以下の 3 種類の提出方法を選びます。

選択肢意味使うタイミング
Commentコメントのみ質問・提案・情報共有
Approve承認マージ可能と判断したとき
Request changes変更要求修正が必要なとき(修正されるまで Approve できない)

gh コマンドによるレビュー操作例を以下に示します。

# PR をレビューして Approve
gh pr review --approve

# 変更を要求してコメントを付ける
gh pr review --request-changes \
  --body "S3 バケットポリシーを追加してください。パブリックアクセスブロック設定も必要です。"

# レビュワーから「Changes requested」が届いた場合の対応
# ローカルで修正後、同じ feature ブランチに追加コミット → push で PR に自動反映
git add modules/s3/
git commit -m "fix: add S3 bucket public access block settings"
git push origin feature/add-s3-module

# Approve 後にマージ(ブランチ保護ルールを満たしている前提)
gh pr merge --squash

ブランチ保護ルール(Branch protection rules)との連携

チームリポジトリでは、Settings → Branches でブランチ保護ルールを設定することが推奨されます。

ルール効果
Require pull request reviews before merging指定人数以上の Approve がなければマージ不可
Require status checks to passCI が green でなければマージ不可
Require branches to be up to datemain の最新コミットを取り込んでからでないとマージ不可
Do not allow bypassing the above settings管理者もルールを迂回できない

これらのルールを設定することで、「うっかり未レビューコードが main に入る」事故を防止できます。


6-8. マージ戦略 3 種の使い分け

GitHub には 3 つのマージ戦略があり、リポジトリごとに「どの戦略を許可するか」を Settings → General → Pull Requests で設定できます。Terraform リポジトリでよく採用されるパターンとともに解説します。

戦略コミット履歴マージコミット適用場面
Merge commitfeature ブランチの全コミットを保持 + マージコミット 1 個追加あり作業の詳細な軌跡を残したいとき。大規模機能開発向き
Squash and mergefeature ブランチの全コミットを 1 コミットに圧縮なし(圧縮コミット 1 個)WIP コミットが多い・履歴をシンプルにしたいとき。小〜中規模機能向き
Rebase and mergefeature ブランチのコミットを main のトップに積み直すなしリニアな履歴にしたいとき。コミット品質が高い(WIP なし)前提

Terraform リポジトリでの推奨

Terraform は terraform apply の実行履歴とコミット履歴を対応させることが多いため、Squash and merge が最も広く採用されています。1 つの PR(= 1 つのインフラ変更)が 1 コミットに対応し、git log で変更の単位が明確になります。

マージ戦略と履歴イメージの対比

main ブランチのコミット履歴がどうなるかを、3 戦略で比べると次のようになります。

Merge commit 後の git log --oneline --graph:

*Merge pull request #1 'feat: add S3 module'
|\
| * fix: add public access block settings
| * feat: add S3 module for static assets
|/
* feat: add VPC module

Squash and merge 後の git log --oneline:

* feat: add S3 module for static assets (#1)
* feat: add VPC module

Rebase and merge 後の git log --oneline:

* fix: add public access block settings
* feat: add S3 module for static assets
* feat: add VPC module

Squash の場合はフィーチャーブランチ内の WIP コミットが 1 つに圧縮されるため、main の履歴がクリーンになります。


6-9. マージ後のブランチ削除

PR がマージされたら feature ブランチは役目を終えます。放置するとブランチが無秩序に増え、リポジトリの見通しが悪くなります。

# ① GitHub.com の PR 画面で「Delete branch」ボタンをクリック(推奨)

# ② gh コマンドでマージと同時にリモートブランチを削除
gh pr merge --delete-branch

# ③ ローカルブランチを削除(リモート削除後に手動で行う)
git switch main
git pull origin main

git branch -d feature/add-s3-module  # マージ済みブランチを削除
git push origin --delete feature/add-s3-module# リモートブランチを明示削除(GitHub UI 操作後は不要)

# ④ リモートで削除済みのブランチをローカルの追跡リストから掃除する
git remote prune origin

# ⑤ 現在のブランチ一覧で削除されていることを確認
git branch -a

「Automatically delete head branches」の設定(推奨)

GitHub の Settings → General → Pull Requests にある 「Automatically delete head branches」 を ON にすると、PR マージのたびに自動でリモートブランチが削除されます。チーム開発では最初に設定しておくことを強く推奨します。

設定場所効果
Automatically delete head branchesSettings → General → Pull RequestsPR マージ後にリモートブランチを自動削除
Allow merge commits同上Merge commit 戦略の許可
Allow squash merging同上Squash merge 戦略の許可
Allow rebase merging同上Rebase merge 戦略の許可

Section 6 のまとめ

Section 6 では、Pull Request の概念から始まり、feature ブランチでの変更作成 → push → PR 作成(GUI / CLI)→ Draft PR → レビューフロー → マージ戦略の選択 → ブランチ削除という、チーム開発の基本サイクルをひと通り体験しました。

Pull Request は「コードを届ける手段」ではなく「コードについて対話する場」です。説明が充実した PR は、数年後のチームメンバー(または未来の自分)への贈り物になります。

Section 6 で学んだ操作の早見表

操作コマンド / 手順
feature ブランチ作成git switch -c feature/xxx
リモートに push(初回)git push -u origin feature/xxx
PR 作成(CLI)gh pr create --fill
Draft PR 作成gh pr create --draft
Draft → Ready に昇格gh pr ready
PR の Approvegh pr review --approve
変更要求gh pr review --request-changes -b "..."
Squash マージgh pr merge --squash
ローカルブランチ削除git branch -d feature/xxx
リモートブランチ削除git push origin --delete feature/xxx
追跡リスト掃除git remote prune origin

Section 7: Issues と Projects によるタスク管理 + PR 連携


7-1. Issue の基本 — タスクとバグを可視化する

Issue(イシュー) は GitHub 上でタスク・バグ・質問・改善提案を追跡するための機能です。Pull Request がコードの変更を管理するのに対し、Issue は「何をすべきか」「何が問題か」 を管理します。

Issue の主な構成要素を整理します。

要素役割設定例
タイトルIssue の内容を一行でfeat: RDS モジュールを Terraform で管理する
本文詳細説明・再現手順・提案内容Markdown 形式で自由記述
ラベルカテゴリ分類(色付きタグ)bug / enhancement / infrastructure
アサイン(Assignees)担当者の指定@alice
マイルストーンリリース計画との紐付けv1.0.0(期日設定可能)
Projectsカンバンボードへの追加IaC Improvements
Related PRs関連する Pull RequestPR 番号を本文に記載すると自動リンク

Issue を起票する際の心構え

Issue は「誰かがいつか見る記録」です。以下の情報を含めると後から読む人(自分も含む)が助かります。

情報バグ Issue の場合機能 Issue の場合
現状(What is happening)エラーメッセージ・スタックトレース現在できないこと
期待値(What should happen)正常時の動作追加後にできること
再現手順 / 提案の背景Step 1, Step 2…ユースケース・技術的動機
影響範囲影響するファイル・モジュール変更するファイル候補
優先度の根拠何人が困っているかビジネス要件

デフォルトラベルとカスタムラベル

GitHub はリポジトリ作成時にデフォルトラベルを自動生成します。Terraform リポジトリでよく追加するカスタムラベルも示します。

ラベル用途デフォルト / カスタム
bugバグ報告デフォルト
enhancement機能追加・改善デフォルト
documentationドキュメント更新デフォルト
good first issue初心者向けのタスクデフォルト
infrastructureTerraform / AWS インフラ関連カスタム
securityセキュリティ関連カスタム
breaking change後方互換性のない変更カスタム
needs discussion設計や方針を議論中カスタム

7-2. Issue テンプレートの設置

チームで Issue の書き方を統一するには、Issue テンプレート が有効です。.github/ISSUE_TEMPLATE/ に YAML 形式のテンプレートファイルを置くと、Issue 作成画面に選択肢として表示されます。

まず mkdir -p .github/ISSUE_TEMPLATE でディレクトリを作成し、以下のテンプレートファイルを配置します。

バグ報告テンプレート(bug_report.yml)

# .github/ISSUE_TEMPLATE/bug_report.yml
name: Bug Report
description: バグや予期しない動作を報告する
title: "fix: "
labels: ["bug"]
body:
  - type: textarea
 id: description
 attributes:
label: 問題の説明
description: 何が起きているか、何が期待されているかを記述してください
placeholder: |
  terraform plan を実行すると以下のエラーが発生します:
  Error: No valid credential sources found
 validations:
required: true

  - type: textarea
 id: steps
 attributes:
label: 再現手順
description: バグを再現するための手順を番号付きで記述してください
value: |
  1. git clone でリポジトリを取得
  2. terraform init を実行
  3. terraform plan を実行
  4. エラーが発生する
 validations:
required: true

  - type: input
 id: terraform_version
 attributes:
label: Terraform のバージョン
placeholder: "例: v1.8.0"
 validations:
required: false

  - type: dropdown
 id: os
 attributes:
label: OS
options:
  - macOS
  - Ubuntu / Debian
  - Windows (WSL2)
  - その他

機能リクエストテンプレート(feature_request.yml)

# .github/ISSUE_TEMPLATE/feature_request.yml
name: Feature Request
description: 新機能や改善提案を起票する
title: "feat: "
labels: ["enhancement"]
body:
  - type: textarea
 id: background
 attributes:
label: 背景・動機
description: なぜこの機能が必要か、現在の問題点を記述してください
 validations:
required: true

  - type: textarea
 id: proposal
 attributes:
label: 提案内容
description: どのような機能を追加・変更したいかを具体的に記述してください
 validations:
required: true

  - type: textarea
 id: acceptance_criteria
 attributes:
label: 受け入れ条件
description: 完了の判断基準をチェックリスト形式で記述してください
value: |
  - [ ] 条件1
  - [ ] 条件2
 validations:
required: false

  - type: textarea
 id: alternatives
 attributes:
label: 検討した代替案
description: 他に検討したアプローチがあれば記述してください
 validations:
required: false

テンプレートを git に追加して main に push します。

git add .github/ISSUE_TEMPLATE/
git commit -m "chore: add GitHub Issue templates for bug report and feature request"
git push origin main

7-3. ハンズオン — Issue 起票 → feature ブランチ → PR → Issue 自動クローズ

GitHub の強力な機能の一つが 「PR のマージで Issue を自動クローズする」 連携です。コミットメッセージや PR 本文に Fixes #N(N は Issue 番号)を含めると、PR がマージされた瞬間に Issue が自動的にクローズされます。

使用できるキーワード

キーワード動作
Fixes #NIssue #N を修正したことを示し、マージ時に自動クローズ
Closes #NFixes と同義(どちらを使っても同じ)
Resolves #NFixes と同義
Related to #N参照リンクを張るが自動クローズはしない

Fixes #2, Fixes #5 のようにカンマ区切りで複数の Issue を指定することも可能です。

ハンズオンを実施します。

# Step 1: gh コマンドで Issue を起票する
gh issue create \
  --title "feat: RDS モジュールを Terraform で管理する" \
  --body "## 背景
現在 RDS インスタンスはコンソールで手動作成している。IaC 化して再現性を確保したい。

## 提案
modules/rds/ を新設し、db.t3.micro の PostgreSQL インスタンスを定義する。

## 受け入れ条件
- [ ] modules/rds/main.tf が存在する
- [ ] terraform plan が正常終了する
- [ ] 変数: instance_class, db_name, username
- [ ] 出力値: endpoint, port" \
  --label "enhancement"

# 作成された Issue の番号を確認(例: #2)
gh issue list

# Step 2: feature ブランチを作成
git switch -c feature/add-rds-module

# Step 3: RDS モジュールのファイルを作成・編集する
mkdir -p modules/rds
# ... エディタでファイルを編集 ...

# Step 4: "Fixes #2" を含むコミットメッセージでコミット
git add modules/rds/
git commit -m "feat: add RDS module for PostgreSQL

- db.t3.micro の PostgreSQL インスタンスを定義
- instance_class / db_name / username を変数化
- endpoint / port を出力値として公開

Fixes #2"

# Step 5: push して PR を作成
git push -u origin feature/add-rds-module
gh pr create --fill

# Step 6: PR がマージされると Issue #2 が自動クローズされる
# (確認方法)
gh issue view 2
# Status: CLOSED と表示されていれば成功

Fixes #N はどこに書けばよいか

書く場所効果
コミットメッセージ本文(Summary 行以外)そのコミットが default branch に到達したときに自動クローズ
PR 本文PR がマージされたときに自動クローズ(推奨)
PR タイトルPR 本文と同様に機能する

コミットメッセージよりも PR 本文に書く方が意図が明確です。1 つの PR が複数 Issue を解決する場合は Fixes #2, Fixes #5 のようにカンマ区切りで列挙できます。


7-4. Projects(Boards V2)での進捗可視化

GitHub Projects は、Issue と PR をカンバンボード形式で管理する機能です。Jira や Trello に相当する機能が GitHub 内で完結します。2022 年にリリースされた Projects V2 は V1 と比較して大幅に機能が強化されており、ロードマップビューやカスタムフィールドが利用できます。

Projects V2 の主な機能

機能説明
ボードビューTo Do / In Progress / Done の列でカンバン管理
テーブルビュースプレッドシート形式で全 Issue を一覧表示
ロードマップビュータイムライン(ガントチャート風)で進捗可視化
カスタムフィールド優先度・見積もり工数・スプリント番号などを追加
自動化「PR がマージされたら Done に移動」などのルール設定
フィルターアサイン・ラベル・マイルストーン・状態で絞り込み

Projects の作成(GitHub.com)

  1. リポジトリのトップページ → Projects タブ → Link a project(または New project
  2. Board テンプレートを選択して作成
  3. To Do / In Progress / Done の列が自動生成される
  4. + Add item から Issue や PR を追加

自動化ルールの設定(推奨設定)

Projects の Settings → Workflows から設定できる自動化ルールを以下に示します。一度設定すると手動でのステータス更新が不要になり、ボードが常に最新状態を反映します。

トリガーアクション
Issue がオープンされたTo Do に追加
PR がオープンされたIn Progress に移動
Issue / PR がクローズされたDone に移動
PR がドラフト解除されたIn Progress に移動

Terraform プロジェクトでの Projects 活用例

使用する Item
Backlog検討中のモジュール追加 Issue
In Design設計中(Draft PR あり)
In Reviewレビュー待ち PR
Doneマージ済み PR / クローズ済み Issue

カスタムフィールドの活用

Projects V2 では、デフォルトの Status 列に加えて独自フィールドを追加できます。Terraform チームでよく使われるカスタムフィールドを以下に示します。

フィールド名種類用途
Priority単一選択(P0/P1/P2/P3)緊急度・重要度の分類
Estimate数値工数見積もり(時間または Story Points)
Sprintイテレーションスプリント(1週間〜2週間の作業単位)
AWS Service単一選択対象 AWS サービス(VPC/RDS/S3 など)
Risk単一選択(Low/Medium/High)変更によるインフラへのリスク評価

カスタムフィールドはテーブルビューで編集すると効率的です。ボードビューでは「Status」フィールドをメインに使いながら、テーブルビューで詳細なメタデータを管理するという使い分けが実践的です。

Milestones との連携

Issues と Projects は Milestones(マイルストーン)とも連携できます。マイルストーンは「v1.0.0」「Sprint 3」のように期日つきのゴールを設定する機能で、関連する Issue をひとまとめにして進捗率を可視化できます。

機能MilestoneProjects
進捗率クローズ済み Issue の割合(%)を自動計算カスタマイズ可能(Done 列のアイテム数など)
期日Due date を設定してカウントダウンロードマップビューで可視化
フィルターis:issue milestone:"v1.0.0"Projects のフィルター機能で絞り込み
粒度リリース単位(粗い)スプリント / タスク単位(細かい)

小規模なチームや個人プロジェクトでは Milestones だけで十分なことが多く、Projects は中規模以上のチームで恩恵が出やすい機能です。


7-5. gh コマンドで CLI 完結のタスク運用

GitHub CLI を使うと、Issue と PR の操作をブラウザを開かずにターミナルで完結できます。開発中にコンテキストを切り替えずに済むため、作業効率が向上します。

# --- Issue 操作 ---

# Issue 一覧(オープン中)を表示
gh issue list

# アサイン済みの Issue のみ表示
gh issue list --assignee "@me"

# ラベルでフィルタリング
gh issue list --label "enhancement"

# Issue の詳細を表示
gh issue view 2

# Issue をクローズする
gh issue close 2

# クローズした Issue を再オープン
gh issue reopen 2

# Issue にコメントを追加
gh issue comment 2 --body "調査完了。RDS モジュールのドラフトを作成中。"

# --- PR 操作 ---

# PR 一覧(オープン中)を表示
gh pr list

# マージ済み PR の一覧
gh pr list --state merged

# 特定の PR の詳細
gh pr view 3

# PR の差分を確認
gh pr diff 3

# PR をローカルにチェックアウト(レビュー時に手元で動作確認)
gh pr checkout 3

# PR を Squash マージしてブランチを自動削除
gh pr merge 3 --squash --delete-branch

# --- ダッシュボード ---

# 自分に関連する Issue / PR の全体状況を確認
gh status

gh status の活用

gh status を実行すると、自分がアサインされている Issue、レビュー待ちの PR、自分が作成した PR の状態が一覧で表示されます。毎朝の作業開始時に gh status を確認する習慣をつけると、今日取り組むべきタスクが即座に把握できます。

CLI ワークフローのベストプラクティス

シーン推奨コマンド
朝の確認gh status
Issue を確認しながら作業gh issue view N
作業完了後に PR 作成gh pr create --fill
レビュー中の変更確認gh pr checkout N && terraform plan
レビュワーへの Approve 要請後確認gh pr view
マージgh pr merge N --squash --delete-branch

GitHub CLI とブラウザ操作の使い分け指針

操作CLI が向く場面ブラウザが向く場面
Issue / PR 作成シンプルな内容・テンプレート不要画像添付・テンプレート選択が必要
レビューコードを手元で動かしながら確認インラインコメントを多数付ける
Projects 管理列のアイテム一覧確認ドラッグ&ドロップでの並び替え
通知確認gh status で要対応を素早く把握通知の詳細を読む

よくあるエラーと対処法

エラー / 症状原因対処法
gh issue create が「No authentication credentials found」で失敗gh auth login が未実施gh auth login --web で認証し直す
PR をマージしても Issue がクローズされないFixes #N をコミットメッセージのサマリー行(1行目)に書いたサマリー行ではなく本文(3行目以降)に書く。または PR 本文に記載する
gh pr create が「No commits between main and feature/xxx」で失敗feature ブランチにコミットがない状態で PR 作成しようとしたファイルを変更して git add && git commit を先に行う
テンプレートが表示されないファイルのパスまたは拡張子が間違っている.github/ISSUE_TEMPLATE/ 直下に .yml 拡張子で配置する
Issue の自動クローズが default branch(main)でのみ動作するGitHub の仕様feature ブランチへのマージでは自動クローズされない。main へのマージが必要

Section 7 のまとめ

Section 7 では、Issue によるタスク可視化、テンプレートによる記述統一、Fixes #N を使った PR との自動連携、Projects ボードによる進捗管理、そして gh コマンドによる CLI 完結の運用方法を学びました。

Issue → feature ブランチ → PR → マージ → Issue 自動クローズ → Projects ボードの Done 移動、というサイクルを一貫して回すことで、「何をするか(Issue)」と「どう変えるか(PR)」が常にトレースできる状態が実現します。これがチーム開発における変更管理の基本形です。

Section 7 で学んだ操作の早見表

操作コマンド / 手順
Issue 起票(CLI)gh issue create --title "..." --label "enhancement"
Issue 一覧gh issue list / gh issue list --assignee "@me"
Issue クローズgh issue close N
PR で Issue 自動クローズPR 本文または commit に Fixes #N を含める
テンプレート設置.github/ISSUE_TEMPLATE/*.yml を作成して push
今日の要対応確認gh status

📝 Section 6〜7 チェックリスト

  • [ ] feature/add-s3-module ブランチを作成して S3 モジュールを追加した
  • [ ] git push -u origin feature/add-s3-module でリモートに push した
  • [ ] Pull Request を作成した(GUI または gh pr create
  • [ ] PR 本文に What / Why / How to test を記述した
  • [ ] Draft PR の作成と gh pr ready による解除を試した
  • [ ] レビューコメントへの対応フロー(Changes requested → 修正 push → Re-review)を理解した
  • [ ] マージ戦略 3 種(Merge commit / Squash / Rebase)の違いを理解した
  • [ ] マージ後に feature ブランチを削除した
  • [ ] Issue テンプレートを .github/ISSUE_TEMPLATE/ に設置した
  • [ ] Fixes #N を含むコミットで PR をマージし、Issue が自動クローズされることを確認した
  • [ ] gh issue listgh pr list で CLI からタスクを確認した
  • [ ] gh status で自分に関連する Issue / PR の全体状況を確認した

Section 8: Fork & 外部コントリビューション + 安全な取り消し


8-1. Fork の概念と Clone との使い分け

GitHub の Fork は「他者のリポジトリを自分のアカウントに丸ごとコピーする」GitHub 上の操作です。git clone とは似ていますが、目的と権限構造が大きく異なります。

比較項目ForkClone
実行場所GitHub の Web UI 上(gh repo fork コマンドも可)ローカル端末のターミナル
コピー先自分の GitHub アカウント(リモートコピー)ローカルマシン(ローカルコピー)
元リポジトリとの関係GitHub 上で “forked from” として紐付きが残る関係なし(remote を追加しない限り)
書き込み権限フォーク先は自分のリポジトリなので自由に push 可clone 元に push できるかは権限次第
主な用途OSS への貢献・実験的な改変・個人的なカスタマイズ既に権限があるリポジトリの作業コピー取得
upstream 追従git remote add upstream + git fetch upstream が必要git pull で元から直接取得できる(権限があれば)

いつ Fork を使うか

  • 自分が contributor でない OSS リポジトリにバグ修正や機能追加を提案したい
  • 公式モジュールをカスタマイズして自社用に改変したい(ただしライセンス確認必須)
  • 破壊的な実験を安全に行いたい(本家を壊すリスクなし)

Clone だけで済むケース

  • 自分または自分のチームが管理するリポジトリへの通常の開発作業
  • 読み取り専用で参照したいだけ(PR を送る予定がない)

8-2. [ハンズオン] 公式 terraform-aws-modules/terraform-aws-vpc を Fork して PR 作成画面まで

実際の OSS モジュールを題材に、Fork → Clone → 修正 → PR 作成画面までの全工程を体験します。PR の実送信は行いません(本番 OSS への未確認送信防止のため)。

⚠️ OSS コントリビューション前の必須確認
実際の OSS に PR を送る前には、必ずリポジトリ内の CONTRIBUTING.mdCODE_OF_CONDUCT.md を読んでください。貢献ガイドライン無視の PR は即クローズされる場合があります。このハンズオンでは PR の実送信を行いません。

Step 1: GitHub UI で Fork

  1. ブラウザで https://github.com/terraform-aws-modules/terraform-aws-vpc を開く
  2. 右上の Fork ボタンをクリック
  3. 「Owner」を自分のアカウントに設定し、Create fork をクリック
  4. 数秒後、https://github.com/YOUR_USERNAME/terraform-aws-vpc が作成される

または gh コマンドで実行する場合:

gh repo fork terraform-aws-modules/terraform-aws-vpc --clone=false

--clone=false を付けると GitHub 側でフォークするだけでローカルには clone しません。

Step 2: Fork したリポジトリを Clone

git clone git@github.com:YOUR_USERNAME/terraform-aws-vpc.git
cd terraform-aws-vpc

clone 後、remote の設定を確認します:

git remote -v
origin  git@github.com:YOUR_USERNAME/terraform-aws-vpc.git (fetch)
origin  git@github.com:YOUR_USERNAME/terraform-aws-vpc.git (push)

現時点では origin が自分のフォーク先のみです。次のステップで本家(upstream)を追加します。

Step 3: 修正用ブランチを作成

git switch -c fix/typo-in-readme

Step 4: README.md の typo を修正

実際に README.md を開き、軽微な typo(例: スペルミス、句読点の欠落)を修正します。

# エディタで README.md を編集後
git diff README.md

差分を確認したら、コミットします:

git add README.md
git commit -m "docs: fix typo in README"

コミットメッセージの書き方: fix: は挙動の修正、docs: はドキュメント変更、feat: は新機能追加を表す Conventional Commits 形式が多くの OSS で採用されています。

Step 5: フォーク先にプッシュ

git push origin fix/typo-in-readme

Step 6: GitHub UI で PR 作成画面を確認

push 後にブラウザで https://github.com/YOUR_USERNAME/terraform-aws-vpc を開くと、“Compare & pull request” ボタンが表示されます。クリックすると PR 作成フォームが開き、base repository: terraform-aws-modules/terraform-aws-vpc への PR 画面が確認できます。

このハンズオンではここで止めます。実際に送信ボタン(”Create pull request”)は押さないでください。


8-3. Upstream 追従 — フォーク元の最新変更を取り込む

Fork したリポジトリは時間が経つと本家(upstream)から遅れます。定期的に upstream の変更を取り込む手順を習得しておきましょう。

upstream リモートを追加

git remote add upstream git@github.com:terraform-aws-modules/terraform-aws-vpc.git

設定を確認:

git remote -v
origin git@github.com:YOUR_USERNAME/terraform-aws-vpc.git (fetch)
origin git@github.com:YOUR_USERNAME/terraform-aws-vpc.git (push)
upstream  git@github.com:terraform-aws-modules/terraform-aws-vpc.git (fetch)
upstream  git@github.com:terraform-aws-modules/terraform-aws-vpc.git (push)

upstream の最新変更を取得

git fetch upstream

fetch はローカルのファイルを変更しません。upstream の最新状態をリモートトラッキングブランチ(upstream/main)として取得するだけです。

rebase で最新化

git switch main
git rebase upstream/main

rebase を使う理由: merge よりもコミット履歴がきれいに保たれ、OSS の PR では rebase が好まれる慣習があります。

フォーク先(origin)を更新

git push origin main

upstream 追従のタイミング

状況推奨アクション
PR 作成前必ず upstream/main にリベースして最新状態を確認
長期間放置したフォークPR 作成前に必ず追従(コンフリクト防止)
定常的な OSS 貢献週1回程度の定期追従で差分を最小化

8-4. git revert — push 済みコミットを安全に取り消す

push 済みのコミットを「なかったこと」にするには git revert を使います。git reset --hard と異なり、新しいコミットを追加することで取り消しを表現するため、共有リポジトリでも安全に使えます。

シナリオ: feature/add-s3-module ブランチをマージした後、S3 モジュールに設定ミスが見つかった。

# 取り消したいコミットの ID を確認
git log --oneline -5
abc1234 feat: add S3 module with lifecycle policy
def5678 docs: update README with S3 module usage
9ab0123 feat: add VPC module
...
# abc1234 のコミットを revert(取り消すコミットを新しいコミットとして追加)
git revert abc1234

エディタが開き、デフォルトのコミットメッセージ(Revert "feat: add S3 module with lifecycle policy")が表示されます。内容を確認して保存するとコミットが作成されます。

# コンフリクトなしで完了した場合
git log --oneline -3
xyz9999 Revert "feat: add S3 module with lifecycle policy"
abc1234 feat: add S3 module with lifecycle policy
def5678 docs: update README with S3 module usage
# リモートに push
git push origin main

複数コミットをまとめて revert する場合

# def5678 から abc1234 まで(新しい順に)revert
git revert def5678..abc1234

または --no-commit で個別にステージングしてまとめてコミット:

git revert --no-commit abc1234 def5678
git commit -m "revert: remove S3 module (config error found)"

8-5. revert vs reset –hard + force push — 判断基準

どちらを使うべきかは「そのコミットが他者と共有されているか」で決まります。

判断軸git revertgit reset –hard + force push
push 済みのコミット安全・推奨⛔ 他者のローカルコピーが破壊される
ローカルのみのコミット使える(ただし不要な revert コミットが残る)✅ 問題なし
コミット履歴の見え方取り消しの記録が残る(透明性が高い)取り消したコミット自体が消える
チーム開発✅ 推奨⛔ 原則禁止(force push でチームが混乱)
個人ブランチ(未マージ)どちらでも可✅ すっきりした履歴になる

判断フロー

コミットを取り消したい
  │
  ├─ そのコミットは既に push 済みか?
  ││
  │├─ YES → git revert を使う(安全)
  ││
  │└─ NO → git reset --hard でローカルのみ修正
  │
  └─ 複数コミットをまとめて取り消したいか?
│
├─ YES → git revert OLDER..NEWER または --no-commit
│
└─ NO → git revert <単一コミットID>
⚠️ force push(–force)は共有ブランチへの原則禁止操作
git push --forceリモートブランチの歴史を書き換え、他の開発者のローカルコピーとの整合性が崩れます。個人ブランチを除き、チームの main / develop などの共有ブランチへの force push は原則禁止です。やむを得ず使う場合は --force-with-lease(他者のプッシュがない場合のみ成功する安全版)を使いましょう。

8-6. OSS コントリビューション時のマナー

OSS への貢献は技術力だけでなくコミュニティとのコミュニケーションが重要です。以下のマナーを守ることで、PR がスムーズにレビュー・マージされる可能性が高まります。

必ず確認すべきファイル

ファイル内容
CONTRIBUTING.mdPR/Issue の書き方、ブランチ命名規則、テスト要件
CODE_OF_CONDUCT.mdコミュニティの行動規範
LICENSEライセンス条件(コントリビューションへの適用確認)
.github/ISSUE_TEMPLATE/Issue 作成時のテンプレート
.github/pull_request_template.mdPR 作成時のテンプレート

コントリビューションのベストプラクティス

  1. Issue を先行作成する: 大きな変更の前に Issue で「こういう修正をしたい」と宣言し、メンテナの合意を得る
  2. 小さな PR を心がける: 変更が小さいほどレビューしやすく、マージされやすい
  3. 既存スタイルに従う: コードフォーマット、コメントの言語(英語が多い)、テスト形式を既存コードから学ぶ
  4. テストを書く: 新機能・バグ修正には対応するテストを追加する
  5. PR 本文を丁寧に書く: What(何を変えたか)・Why(なぜ変えるか)・How to test(確認方法)を明記
  6. レビュー指摘には感謝を示す: 指摘は攻撃ではなくコードへのフィードバック。感謝の気持ちを添えて対応

Section 8 チェックリスト

📝 Section 8 チェックリスト

  • [ ] Fork と Clone の違いをテーブルで説明できる
  • [ ] GitHub UI または gh repo fork で Fork を作成できた
  • [ ] git switch -c でブランチを作成し修正・コミット・push できた
  • [ ] git remote add upstream で本家を追加した
  • [ ] git fetch upstream && git rebase upstream/main で upstream 追従できた
  • [ ] git revert で push 済みコミットを安全に取り消せた
  • [ ] revert と reset –hard の使い分け基準を説明できる
  • [ ] OSS 貢献前に CONTRIBUTING.md を確認する習慣を理解した

Section 9: リポジトリ運用 Tips + トラブルシューティング


9-1. ブランチ保護ルール — レビューと CI を強制する

チーム開発では「誰でも main に直接 push できる」状態は危険です。GitHub のブランチ保護ルール(Branch Protection Rules)を設定することで、PR レビューや CI パス(terraform plan など)を必須化できます。

GUI での設定

  1. リポジトリの SettingsBranchesAdd rule
  2. 「Branch name pattern」に main を入力
  3. 以下のオプションを有効化:
  4. Require a pull request before merging(PR 必須)
  5. Require approvals → Approvals: 1(1名以上のレビュー承認必須)
  6. Require status checks to pass before merging(CI 必須)
  7. Include administrators(管理者も対象に)

gh CLI での設定

gh api repos/YOUR_USERNAME/terraform-git-handson/branches/main/protection \
  --method PUT \
  --field required_pull_request_reviews='{"required_approving_review_count":1}' \
  --field enforce_admins=true \
  --field restrictions=null \
  --field required_status_checks='{"strict":true,"contexts":[]}'

required_approving_review_count は必要な承認者数です。チームの規模に応じて調整します。

設定後の効果

操作ルール設定前ルール設定後
git push origin main成功❌ 拒否(”protected branch” エラー)
PR なしの直接マージ可能❌ 不可
未承認 PR のマージ可能❌ 不可(Approve 必須)
CI 失敗時のマージ可能❌ 不可(status check 必須時)
💡 第5弾 OIDC CI/CD への布石
第5弾では GitHub Actions と AWS OIDC を組み合わせた CI/CD パイプラインを構築します。ブランチ保護ルールで required_status_checks に GitHub Actions の workflow を指定することで、terraform plan の成功を PR マージの必須条件にできます。今ここで保護ルールの概念を理解しておくことが後続の学習に直結します。

9-2. CODEOWNERS — 自動レビュアー割当

CODEOWNERS ファイルを使うと、特定のファイル・ディレクトリへの変更が含まれる PR に、対応するチームや個人を自動でレビュアーとして追加できます。

ファイルの配置場所(どちらか一つ)

  • .github/CODEOWNERS
  • CODEOWNERS(リポジトリルート)

書き方

# .github/CODEOWNERS
# 書式: <パターン> <GitHubユーザー or チーム>

# modules/vpc/ 以下のファイルは infrastructure チームが自動レビュアー
modules/vpc/@your-team/infrastructure

# modules/s3/ 以下は infrastructure チームが担当
modules/s3/ @your-team/infrastructure

# ルートの main.tf は特定のシニアエンジニアがレビュー
main.tf  @senior-engineer

# .github/ 以下の変更は DevOps チームが担当
.github/ @your-team/devops

# デフォルト(上記以外の全ファイル)
*  @your-username

パターン記法

パターンマッチする対象
*.tf.tf ファイル(サブディレクトリも含む)
modules/modules/ ディレクトリ以下の全ファイル
docs/*.mddocs/ 直下の .md ファイル
/main.tfリポジトリルートの main.tf のみ

CODEOWNERS を有効にするには、ブランチ保護ルールで “Require review from Code Owners” を有効化する必要があります。


9-3. Pull Request テンプレートで PR 品質を均一化

.github/pull_request_template.md を作成すると、PR 作成時にテンプレートが自動的に本文フィールドに挿入されます。

mkdir -p .github
# .github/pull_request_template.md
## 変更内容 (What)

<!-- この PR で何を変更しましたか? -->

## 変更理由 (Why)

<!-- なぜこの変更が必要ですか?関連 Issue: Fixes #N -->

## 確認方法 (How to test)

- [ ] `terraform fmt` を実行した
- [ ] `terraform validate` を実行した
- [ ] `terraform plan` の出力を確認した(差分を PR コメントに貼付推奨)
- [ ] ローカルで動作確認を行った

## スクリーンショット / terraform plan 出力(任意)

<!-- 変更の視覚的確認が必要な場合に追加 -->

このテンプレートをコミット・push すると、以降すべての PR でこのフォームが使われます:

git add .github/pull_request_template.md
git commit -m "chore: add pull request template"
git push origin main

9-4. Secret Scanning & Dependabot — セキュリティの基礎

第4弾セキュリティ編への布石として、GitHub が提供する自動セキュリティ機能の概要を把握しておきます。

Secret Scanning

push されたコードに API キー・トークン・パスワードなどの秘密情報が含まれていないかを自動検出します。

機能内容
Push protection秘密情報を含む push をブロック(事前防止)
Secret scanning alerts既存コードに含まれる秘密情報を検出してアラート
Partner patternsGitHub が主要サービス(AWS、Stripe 等)のトークン形式を認識
Custom patterns独自のトークン形式を正規表現で定義可能(Enterprise)

有効化: SettingsSecurityCode security and analysisSecret scanning を ON

⚠️ Terraform ユーザーへの注意
terraform.tfvars*.auto.tfvars には AWS アクセスキーや DB パスワードなどが含まれることがあります。必ず .gitignore に追記し、絶対に commit しないでください。Secret Scanning の Push protection を有効にしておくことで、万一の commit 時にもブロックできます。

Dependabot

依存ライブラリ・アクションの脆弱性を検出し、自動で PR を作成してアップデートを提案します。

# .github/dependabot.yml
version: 2
updates:
  # GitHub Actions のバージョン自動更新
  - package-ecosystem: "github-actions"
 directory: "/"
 schedule:
interval: "weekly"

Terraform Provider の自動更新は Dependabot の terraform エコシステム対応(2024年以降 GA)で設定可能です。


9-5. トラブルシューティング早見表

よくあるエラーと対処法を一覧にまとめます。エラーメッセージと状況を照合して、素早く解決できるようにしましょう。

症状主な原因対処法
push rejected (non-fast-forward)リモートに自分が持っていない新コミットがあるgit pull --rebase origin main && git push
PR conflictingfeature ブランチが古く、main と diverge しているgit fetch origin && git rebase origin/main でブランチを最新化
gone ブランチが表示されるリモートブランチが削除された後、ローカルに参照が残っているgit remote prune origin でローカルの参照を整理
大容量ファイルを push できない(100MB 超)GitHub の単一ファイル上限(100MB)に引っかかったgit rm --cached <file> + .gitignore 追記。次回から commit しない
fatal: refusing to merge unrelated histories異なるルートを持つリポジトリを merge しようとしたgit pull origin main --allow-unrelated-histories(初回のみ)
error: failed to push some refsローカルブランチがリモートより古いまず git fetch && git status で状況確認、rebase か merge で解決
コミットに間違ったメールアドレスが含まれていたgit config が正しく設定されていなかった未push なら git commit --amend、push済みなら git revert
PR がマージできない(status check 失敗)CI(GitHub Actions / terraform plan)が失敗しているワークフローのログを確認し、コードを修正して再 push

ブランチ状態の確認コマンド

# ローカルブランチとリモートブランチの対応状態を確認
git branch -vv
* feature/add-s3-module  abc1234 [origin/feature/add-s3-module] feat: add S3 module
  main def5678 [origin/main] Initial commit

[origin/feature/add-s3-module] の後に ahead N / behind N が表示されると、push 不足やリモートとの差分が確認できます。

# リモート情報を最新化してブランチ状態を確認
git fetch --prune && git branch -vv

--prune オプションで、削除済みのリモートブランチへのローカル参照を自動的にクリーンアップします。


Section 9 チェックリスト

📝 Section 9 チェックリスト

  • [ ] main ブランチにブランチ保護ルール(PR 必須 + Approve 1名)を設定した
  • [ ] .github/CODEOWNERS を作成し、modules/ ディレクトリのオーナーを設定した
  • [ ] .github/pull_request_template.md を作成し PR フォームを統一した
  • [ ] Secret Scanning(Push protection)を有効化した
  • [ ] .github/dependabot.yml で GitHub Actions の自動更新を設定した
  • [ ] トラブルシューティング早見表で主要エラーの対処法を確認した

Section 10: まとめ・次のステップ・参考リンク


10-1. 本記事で習得したスキル

第1弾(ローカル Git 入門)と第2弾(GitHub リモート協業)の 2 記事を通じて、ソロ開発からチーム開発まで必要な Git/GitHub の基礎スキルが揃いました。

第2弾(本記事)で習得したスキル一覧

スキル主要コマンド / 操作
GitHub アカウント作成・認証設定SSH keygen / Fine-grained PAT / gh auth login
リモートリポジトリ作成gh repo create / GitHub UI
初回プッシュgit remote add origin + git push -u origin main
リモート変更の取得git fetch / git pull / git pull --rebase
Pull Request の作成gh pr create / GitHub UI
PR レビューの実施gh pr review / GitHub UI コメント
PR のマージ戦略Merge commit / Squash / Rebase merge
Issue 管理gh issue create / gh issue list / Fixes #N 自動クローズ
Issue テンプレート.github/ISSUE_TEMPLATE/*.md の作成
Fork & upstream 追従gh repo fork / git remote add upstream / git rebase upstream/main
安全なコミット取り消しgit revert <commit>
ブランチ保護ルールGitHub Settings / gh api での設定
CODEOWNERS.github/CODEOWNERS の作成・運用
PR テンプレート.github/pull_request_template.md
Secret ScanningPush protection の有効化
トラブルシューティングgit branch -vv / git remote prune origin / rebase 解決

10-2. 第1弾 + 第2弾完走で可能になったこと

第1弾のみ(ローカル完結)でできること

  • ファイルの変更履歴を Git で管理する
  • ブランチを使って実験的な変更を安全に行う
  • ローカルでマージしてコンフリクトを解決する

第2弾完了後(リモート協業)で追加できること

  • Terraform コードをクラウド(GitHub)でバックアップ・共有する
  • Pull Request でチームメンバーからレビューを受けて品質を高める
  • Issue でタスクを管理し、PR とリンクして進捗を可視化する
  • OSS の公式モジュール(terraform-aws-modules 等)へ貢献するフローを理解する
  • push 済みのミスを git revert で安全に取り消せる
  • ブランチ保護と CODEOWNERS でリポジトリのガバナンスを強化する

10-3. 次のステップ — 第3弾: ブランチ戦略プレビュー

第2弾では「feature ブランチを作って main にマージする」という基本フローを習得しました。第3弾では、チーム規模や開発サイクルに応じたブランチ戦略の選択と運用を学びます。

第3弾で扱うテーマ(予定)

テーマ概要
GitFlowfeature/ release/ hotfix/ develop/ main の 5 ブランチ構成
Trunk-based developmentmain への短命ブランチ + Feature Flags による継続的インテグレーション
リリース戦略セマンティックバージョニング・タグ付け・GitHub Releases
Squash vs Rebase vs Mergeチームに最適なマージ戦略の選び方
Terraform × ブランチ戦略環境別ディレクトリ構成と IaC ブランチモデルの実践

10-4. シリーズロードマップ

📚 Git/GitHub × Terraform実践シリーズ — 全体ロードマップ

各記事は独立して読めますが、第1弾→第2弾→第3弾の順に進むと、ローカル Git からチーム協業、本番運用まで一本の学習パスとして体系的に習得できます。


10-5. 参考リンク

GitHub 公式ドキュメント

リンク内容
GitHub Docs — Pull requestsPR 作成・レビュー・マージの公式ガイド
GitHub Docs — ForksFork の管理と upstream 追従
GitHub Docs — Branch protectionブランチ保護ルールの設定
GitHub Docs — CODEOWNERSCODEOWNERS ファイルの書き方
GitHub Docs — Secret scanningSecret Scanning の設定と運用
GitHub Docs — DependabotDependabot の設定ファイル仕様

GitHub Skills(インタラクティブ学習)

リンク内容
GitHub Skills — Introduction to GitHubGitHub の基本を対話形式で学習
GitHub Skills — Review pull requestsPR レビューの練習
GitHub Skills — Resolve merge conflictsコンフリクト解決の練習

gh CLI

リンク内容
gh CLI マニュアルgh コマンド全リファレンス
gh CLI リリースページ最新バージョンのダウンロード

OSS コントリビューション

リンク内容
Open Source Guides — How to ContributeOSS 貢献の心構えと実践ガイド
Conventional Commitsコミットメッセージの標準仕様(日本語)
terraform-aws-modulesハンズオンで使用した公式 Terraform モジュール集

📝 第2弾 全体チェックリスト

  • [ ] GitHub アカウントを作成し、SSH 認証または Fine-grained PAT を設定した
  • [ ] gh auth login で GitHub CLI の認証を完了した
  • [ ] ローカルリポジトリをリモート(GitHub)に push した
  • [ ] git fetchgit pull の違いを説明できる
  • [ ] feature ブランチから Pull Request を作成し、マージした
  • [ ] Issue を作成し、Fixes #N で PR とリンクして自動クローズを確認した
  • [ ] gh pr create / gh issue create など CLI 操作を実践した
  • [ ] terraform-aws-vpc を Fork し、upstream 追従の手順を理解した
  • [ ] git revert で push 済みコミットを安全に取り消せた
  • [ ] main ブランチにブランチ保護ルールを設定した
  • [ ] .github/CODEOWNERS と PR テンプレートを作成した
  • [ ] Secret Scanning を有効化し、Dependabot の設定を行った