😸

Git/Github CLI チートシート & ベストプラクティス

に公開

備忘録

Git 基本コマンド

ref: git(https://git-scm.com/docs)

初期設定とリポジトリ操作

# ユーザー設定
git config --global user.name "Your Name"       # グローバル設定
git config --global user.email "email@example.com"
git config --local user.name "Your Name"        # リポジトリ単位の設定
git config --local user.email "email@example.com"

# リポジトリ作成
git init                                        # 新規リポジトリ初期化

# リポジトリのクローン
git clone git@github.com:<owner>/<repo>.git     # SSH接続
git clone https://<token>@github.com/<owner>/<repo>.git  # HTTPS (トークン使用)

状態確認コマンド

# 状態確認
git status                                      # 作業状態確認
git diff                                        # 変更差分表示(ステージ前)
git diff --staged                               # 変更差分表示(ステージ済み)

# 履歴確認
git log                                         # コミット履歴表示
git log --oneline --graph --decorate            # グラフィカルな履歴表示
git show <commit>                               # 特定コミットの詳細表示

# リモート管理
git remote -v                                   # リモート一覧確認

変更管理

# ステージング
git add <file>                                  # 特定ファイルをステージ
git add .                                       # すべての変更をステージ

# コミット
git commit -m "コミットメッセージ"                # 変更をコミット
git commit -am "メッセージ"                      # ステージング+コミット

# 変更取り消し
git reset HEAD <file>                           # ステージ解除
git reset --soft HEAD^                          # 直前のコミットを取り消し(変更は保持)
git reset --hard HEAD^                          # 直前のコミットを完全に取り消し
git revert <commit>                             # コミットを打ち消す新コミットを作成

ブランチ操作

# ブランチ管理
git branch                                      # ブランチ一覧表示
git branch -avv                                 # リモートも含めたブランチ詳細

# ブランチ作成・切替
git checkout -b <branch>                        # ブランチ作成&切替
git switch -c <branch>                          # ブランチ作成&切替 (Git 2.23+)
git checkout <branch>                           # ブランチ切替
git switch <branch>                             # ブランチ切替 (Git 2.23+)

# ブランチ統合
git merge <branch>                              # 現在のブランチに<branch>をマージ
git rebase <branch>                             # 現在のブランチを<branch>にリベース
git cherry-pick <commit>                        # 特定コミットを現在のブランチに適用

# コンフリクト解決
git merge --continue                            # コンフリクト解決後にマージ続行
git rebase --continue                           # コンフリクト解決後にリベース続行

リモート連携

# リモート管理
git remote add origin <url>                     # リモート追加
git remote remove <name>                        # リモート削除

# リモート同期
git fetch <remote>                              # リモート変更取得
git pull <remote> <branch>                      # リモート変更取得&マージ
git pull --rebase <remote> <branch>             # リモート変更取得&リベース
git push -u <remote> <branch>                   # ローカル変更をリモートへ反映

# タグ操作
git tag <tagname>                               # タグを作成
git push <remote> --tags                        # すべてのタグをリモートに反映

高度な操作

# 部分的な操作
git fetch <remote> refs/changes/34/1234/1      # 特定の変更のみ取得
git checkout FETCH_HEAD                         # 取得した変更をチェックアウト
git cherry-pick <start>^..<end>                # 範囲指定cherry-pick

# 最適化
git gc --aggressive --prune=now                 # リポジトリを最適化

Git Hooks

Git Hooksはコミットやプッシュなどの特定のイベント発生時に自動的にスクリプトを実行する仕組みです。

ref: githooks(https://git-scm.com/docs/githooks)
ref: Git hooks入門

基本設定

# Hooks用ディレクトリ作成
mkdir -p .githooks

# Git設定(リポジトリごと)
git config core.hooksPath .githooks

# 実行権限付与
chmod -R +x .githooks/

主なHookの種類

Hook名 実行タイミング 主な用途
pre-commit コミット前 コード整形、リント、簡易テスト
pre-push プッシュ前 大規模テスト、ビルド確認
commit-msg コミットメッセージ保存前 メッセージフォーマット検証
post-commit コミット後 通知、バージョン更新
post-merge マージ後 依存関係更新、環境同期

基本的なHookの例

pre-commit (コード検証)

#!/bin/sh
echo "Running pre-commit hooks..."

# ステージされたJSファイルを検出
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')

if [ -n "$STAGED_FILES" ]; then
  # ESLintによるコード検証
  npx eslint $STAGED_FILES
  if [ $? -ne 0 ]; then
    echo "ESLint failed! コミットを中止します"
    exit 1
  fi
fi

exit 0

commit-msg (コミットメッセージ検証)

#!/bin/sh
# コミットメッセージの形式を検証
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat $COMMIT_MSG_FILE)

# Conventional Commitsの形式に従っているか検証
if ! echo "$COMMIT_MSG" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+"; then
  echo "コミットメッセージが規約に従っていません"
  echo "例: feat: 新機能追加 または fix: バグ修正"
  exit 1
fi

exit 0

実用的なHook実装例

テスト自動実行 (pre-commit)

#!/bin/sh
# 変更されたファイルに対応するテストを実行
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')

if [ -z "$STAGED_FILES" ]; then
  exit 0
fi

echo "Running tests for staged files..."

for FILE in $STAGED_FILES; do
  TEST_FILE=$(echo $FILE | sed 's/\.js$/_test.js/')
  if [ -f "$TEST_FILE" ]; then
    echo "Testing: $TEST_FILE"
    npx jest "$TEST_FILE"
    if [ $? -ne 0 ]; then
      echo "Tests failed: $TEST_FILE"
      exit 1
    fi
  fi
done

echo "All tests passed!"
exit 0

コード整形 (pre-commit)

#!/bin/sh
# JavaScriptファイルをPrettierで整形
STAGED_JS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx)$')
if [ -n "$STAGED_JS_FILES" ]; then
  echo "Formatting JavaScript/TypeScript files..."
  npx prettier --write $STAGED_JS_FILES
  git add $STAGED_JS_FILES
fi

# Pythonファイルをblackで整形
STAGED_PY_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
if [ -n "$STAGED_PY_FILES" ]; then
  echo "Formatting Python files..."
  black $STAGED_PY_FILES
  git add $STAGED_PY_FILES
fi

exit 0

セキュリティスキャン (pre-push)

#!/bin/sh
echo "Running security checks..."

# 依存関係の脆弱性チェック
if [ -f "package.json" ]; then
  npm audit --audit-level=high
  if [ $? -ne 0 ]; then
    echo "Security vulnerabilities found!"
    echo "Run 'npm audit fix' to resolve or use --no-verify to bypass"
    exit 1
  fi
fi

# シークレットスキャン
if command -v detect-secrets &> /dev/null; then
  detect-secrets scan
  if [ $? -ne 0 ]; then
    echo "Potential secrets detected in code!"
    exit 1
  fi
fi

exit 0

バージョン番号の自動更新 (post-commit)

#!/bin/sh
BRANCH=$(git rev-parse --abbrev-ref HEAD)

# mainブランチのみバージョン更新
if [ "$BRANCH" = "main" ]; then
  echo "Updating version number..."
  
  if [ -f "package.json" ]; then
    # パッチバージョンを更新
    VERSION=$(npm version patch --no-git-tag-version)
    echo "Updated to $VERSION"
    
    git add package.json package-lock.json
    git commit --amend --no-edit
  fi
fi

exit 0

GitHub CLI コマンド

GitHub CLIは、ターミナルからGitHubの機能を操作するためのコマンドラインツールです。

ref: gh(https://cli.github.com/manual/)

認証とセットアップ

# GitHubアカウント認証
gh auth login                                   # 対話形式でログイン
echo "<token>" | gh auth login --with-token    # トークンでログイン

# SSHキー生成・登録
ssh-keygen -t ed25519 -C "email@example.com"   # SSHキー作成
gh ssh-key add ~/.ssh/id_ed25519.pub           # GitHubにSSHキー追加

リポジトリ操作

# リポジトリ作成
gh repo create <name> --public --source=.      # カレントディレクトリから作成
gh repo create <name> --private --clone        # プライベートリポジトリ作成&クローン

# リポジトリ取得
gh repo clone <owner>/<repo>                   # リポジトリをクローン
gh repo fork <owner>/<repo> --clone=true       # リポジトリをフォーク&クローン

# リポジトリ管理
gh repo view <owner>/<repo> --web              # ブラウザでリポジトリを開く
gh repo delete <owner>/<repo> --confirm        # リポジトリを削除

Issue管理

# Issue操作
gh issue list                                  # Issue一覧表示
gh issue list --state open --label bug         # フィルタ付きIssue一覧
gh issue create --title "タイトル" --body "内容"  # Issue作成
gh issue view <number>                         # Issue詳細表示
gh issue close <number>                        # Issueをクローズ

# 高度な検索・フィルタリング
gh issue list --json number,title,labels --jq '.[] | select(.labels[].name == "bug")'

プルリクエスト操作

# PR作成・確認
gh pr create --title "タイトル" --body "説明"     # PR作成
gh pr list                                      # PR一覧表示
gh pr view <number>                            # PR詳細表示
gh pr checkout <number>                        # PRをチェックアウト

# PRレビュー・マージ
gh pr review <number> --approve                # PRを承認
gh pr merge <number> --merge                   # マージコミットでマージ
gh pr merge <number> --squash                  # スカッシュマージ
gh pr merge <number> --rebase                  # リベースマージ

その他の機能

# 通知管理
gh notification list --limit 20 --unread       # 未読通知一覧

# ワークフロー操作
gh workflow list                               # ワークフロー一覧
gh run list --workflow=ci.yml                  # 実行履歴一覧
gh run view <run-id>                           # 実行詳細表示
gh run rerun <run-id>                          # ワークフロー再実行

# エイリアス設定
gh alias set prc 'pr create --title "$1" --body "$2"'
gh alias list                                  # エイリアス一覧表示

拡張機能と高度な操作

# Gist操作
gh gist create --public file.txt               # Gist作成
gh gist list --limit 10                        # Gist一覧

# Codespace操作
gh codespace create --repo <owner>/<repo>      # Codespace作成
gh codespace list                              # Codespace一覧

# API活用
gh api graphql -f query='{ viewer { login } }'  # GraphQL API呼び出し
gh search repos "language:go"      # リポジトリ検索

ref: gh api(https://cli.github.com/manual/gh_api)
ref: gh search repos(https://cli.github.com/manual/gh_search_repos)

ベストプラクティス

ブランチ戦略

戦略 特徴 適したプロジェクト
Git Flow main, develop, feature/*, release/*, hotfix/* 大規模チーム、計画的リリース
GitHub Flow main + 機能ブランチ、PR駆動 継続的デリバリー、シンプルな開発
GitLab Flow main, pre-production, production 環境ごとのデプロイ管理

ref: A successful Git branching model
ref: Combine GitLab Flow and GitLab Duo for a workflow powerhouse
ref: Gitにおけるブランチ戦略について調べてみた

ブランチ命名規則

<タイプ>/<イシュー番号>-<簡潔な説明>

例:
feature/123-user-authentication
fix/456-login-error
docs/789-api-documentation

プレフィックスの例:

  • feature/ - 新機能開発
  • fix/ - バグ修正
  • hotfix/ - 緊急対応
  • docs/ - ドキュメント更新
  • chore/ - 雑務作業
  • refactor/ - リファクタリング

ref: Git ブランチの命名規則

コミットメッセージ規約

Conventional Commitsに従ったメッセージ形式:

<型>[任意 スコープ]: <タイトル>

[任意 本文]

[任意 フッター]

:

feat(auth): ログイン機能を実装

- JWTトークン認証を導入
- リフレッシュトークンの仕組みを追加

Closes #123
仕様(抜粋)
  1. コミットは featfix などの型から始まり (MUST)、その後ろにはスコープ (OPTIONAL) と ! (OPTIONAL) が続き、その後ろにコロンとスペース (REQUIRED) が続く。
  2. コミットがあなたのアプリケーションやライブラリに新しい機能を追加するとき、型 feat が使われなければならない (MUST)。
  3. コミットがあなたのアプリケーションのためのバグ修正を行うとき、型 fix が使われなければならない (MUST)。
  4. スコープを型の後ろに記述してもよい (MAY)。スコープは、コードベースのセクションを記述する括弧で囲まれた名詞にしなければならない (MUST)。例: fix(parser):
  5. 型/スコープの後ろのコロンとスペースの直後にタイトルが続かなければならない (MUST)。 タイトルはコード変更の短かい要約である。例: fix: array parsing issue when multiple spaces were contained in string
  6. 破壊的変更は、コミットの型/スコープの接頭辞か、フッターによって明示されなければならない (MUST)。
  7. Conventional Commits を構成する情報の単位は、大文字の BREAKING CHANGE を除いて、実装は大文字と小文字を区別してはならない (MUST NOT)。

ref: Conventional Commits 1.0.0

例: タイトルおよび破壊的変更のフッターを持つコミットメッセージ

feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

例: スコープおよび破壊的変更を目立たせるための ! を持つコミットメッセージ

feat(api)!: send an email to the customer when a product is shipped

ref: Conventional Commits 1.0.0
ref: Gitのコミットメッセージの書き方
ref: 僕が考える最強のコミットメッセージの書き方
ref: Gitのコミットメッセージの書き方(2023年ver.)

CHANGELOG自動生成

GitHub Actionsを使用して自動的にCHANGELOGを生成する例:

name: Release Changelog

on:
  push:
    tags:
      - 'v*'

jobs:
  changelog:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Generate Changelog
        id: changelog
        uses: spring-io/github-changelog-generator@v0.0.13
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          
      - name: Create Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref_name }}
          release_name: Release ${{ github.ref_name }}
          body: ${{ steps.changelog.outputs.changelog }}

ref: Conventional CommitsとCHANGELOGの自動生成でリリースのユーザ影響をわかりやすくした話
ref: GitHubで使えるリリースノート(ChangeLog)自動生成ツール3選(2021年版)

SSHによるGitHub認証設定

  1. 鍵生成:

    cd ~/.ssh
    ssh-keygen -t ed25519 -C "email@example.com"
    
  2. 設定ファイル作成:

    # ~/.ssh/config
    Host github.com
      HostName github.com
      User git
      IdentityFile ~/.ssh/id_ed25519
    
  3. 公開鍵をGitHubに登録:

    # キーをクリップボードにコピー
    pbcopy < ~/.ssh/id_ed25519.pub  # Mac
    clip < ~/.ssh/id_ed25519.pub    # Windows
    

    GitHubの設定画面でSSHキーを追加

  4. 接続テスト:

    ssh -T git@github.com
    

ref: GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~

ローカルでのGitHub Actions実行

nektos/actを使用して、GitHub Actionsをローカルで実行できます:

# インストール
brew install act  # macOS

# 使用例
act                                 # すべてのワークフローを実行
act -j <job_id>                     # 特定のジョブのみ実行
act -n                              # ドライラン(実行せず確認のみ)
act -s SECRET_NAME=value            # シークレット指定
act --container-architecture linux/amd64  # アーキテクチャ指定(M1/M2 Mac向け)

ref: actを使ってGitHub Actionsをローカル実行する
ref: ローカルで GitHub Actions が実行できる act のお作法を整理する

Monorepoのベストプラクティス

Monorepoとは複数のプロジェクトやパッケージを単一のリポジトリで管理する手法です。

Monorepoの基本構成

monorepo/
├── packages/
│   ├── package-a/
│   │   ├── package.json
│   │   └── src/
│   ├── package-b/
│   │   ├── package.json
│   │   └── src/
├── apps/
│   ├── web/
│   │   ├── package.json
│   │   └── src/
│   ├── mobile/
│   │   ├── package.json
│   │   └── src/
├── package.json
├── lerna.json / pnpm-workspace.yaml / nx.json
└── README.md

パッケージマネージャーと管理ツール

ツール 主な機能 特徴
Lerna パッケージ管理、バージョン管理 従来からのモノレポ管理ツール
Nx ビルドシステム、依存管理、キャッシュ スケールに強い高機能フレームワーク
Turborepo ビルドシステム、高速キャッシュ シンプルで高速なタスク実行
pnpm パッケージマネージャー、ワークスペース ディスク効率と高速インストール
Yarn Workspaces パッケージ管理、ホイスティング(Hoisting) Yarnに統合されたワークスペース

Git関連の設定例

.gitignore

# 共通の除外設定
node_modules/
dist/
.env
*.log

# パッケージ固有の除外設定
packages/*/.cache
apps/*/build

.gitattributes (大規模リポジトリ向け)

# バイナリファイルとテキストファイルの区別
*.png binary
*.jpg binary
*.pdf binary

# 改行コード統一
*.js text eol=lf
*.ts text eol=lf
*.json text eol=lf
*.md text eol=lf

ref: gitattributes(https://git-scm.com/docs/gitattributes)

コミット戦略

  1. スコープを明確に:

    feat(web): ヘッダーコンポーネントを追加
    fix(shared): 型定義の不具合を修正
    
  2. 複数パッケージの変更:

    feat(api,web): 認証機能を実装
    
  3. 共通変更:

    chore: 全パッケージの依存関係を更新
    

Gitワークフロー最適化

# 特定パッケージの変更のみをコミット
git add packages/specific-package/

# 前回のコミット以降の特定ディレクトリの変更を確認
git diff HEAD~1 -- packages/package-a/

# マージ時のコンフリクト解決を容易にするためのリベース
git pull --rebase origin main

# 特定パッケージの履歴のみを表示
git log -- packages/package-a/

CI/CD設定 (GitHub Actions例)

name: Monorepo CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      package-a: ${{ steps.filter.outputs.package-a }}
      package-b: ${{ steps.filter.outputs.package-b }}
    steps:
      - uses: actions/checkout@v3
      - uses: dorny/paths-filter@v2
        id: filter
        with:
          filters: |
            package-a:
              - 'packages/package-a/**'
            package-b:
              - 'packages/package-b/**'

  build-package-a:
    needs: detect-changes
    if: ${{ needs.detect-changes.outputs.package-a == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build Package A
        run: |
          cd packages/package-a
          npm ci
          npm run build

ref: モノレポでGitHub Actionsをいい感じにやるチップス
ref: モノレポでの無駄な GitHub Actions の実行を避ける
ref: モノリポでGitHub Actionsで効率よくCI/CDや自動化を実装するTips 3選

パフォーマンス最適化

  1. Sparse Checkout:

    # 特定のサブディレクトリのみをチェックアウト
    git clone --filter=blob:none --sparse https://github.com/org/monorepo.git
    cd monorepo
    git sparse-checkout set packages/package-a apps/web
    

    ref: git の sparse-checkout を使ってモノリポでも快適にいこう!

  2. Shallow Clone:

    # 履歴を制限してクローン
    git clone --depth=1 https://github.com/org/monorepo.git
    

    ref: Get up to speed with partial clone and shallow clone

  3. Git LFS (大きなバイナリファイル向け):

    # Git LFSの設定
    git lfs install
    git lfs track "*.bin" "*.model"
    git add .gitattributes
    

    ref: git-lfs(https://git-lfs.com/docs)

ベストプラクティス総括

  1. モジュール構造: 明確な責任分離と適切なパッケージ境界を設定
  2. 依存関係管理: 循環依存を避け、方向性のある依存グラフを維持
  3. ビルドツール: Nx/Turborepoなどでビルドを最適化・並列化
  4. 変更検出: 影響を受けるパッケージのみをビルド/テスト
  5. バージョン管理: 一貫した戦略でパッケージのバージョンを管理
    • 独立バージョン: 各パッケージが独自のバージョンを持つ
    • 固定バージョン: すべてのパッケージが同じバージョンを共有
  6. 贅沢なテスト: ユニットテスト、統合テスト、E2Eテストを効率的に実施
  7. ドキュメント: 各パッケージの目的、API、使用例を明確に記述

ref: Building a Monorepo: The Right way

Discussion