2026年メンテナンス注記:ページ末尾に2019年の原エクスポート本文を一字一句そのまま保存しています。旧文は
masterへ直接統合する手順で、原文の誤記も含みます。現在の操作手順ではなく、履歴資料として読んでください。以下のメンテナンス版は、プルリクエストまたはマージリクエストを扱えるGitホスティングサービスを前提としています。mainは実際のデフォルトブランチ名に置き換え、リポジトリに明記されたチーム方針に従ってください。
Table of Contents
小規模チームの約束
コマンドを選ぶ前に、次の4点を合意します。
- デフォルトブランチとリリースブランチを保護し、通常作業では直接プッシュしない。
- 変更ごとに短命な作業ブランチを作り、レビューを通して統合する。
- レビュー依頼前にリポジトリ所定のテストを実行し、正確な差分を確認する。
- 他の人が作業の基点にした可能性のあるブランチの履歴を変更しない。
Git自体はレビューを強制しませんが、ホスティングサービスは強制できます。たとえばGitHubのブランチ保護では、プルリクエストのレビュー、ステータスチェックの成功、会話の解決を必須にし、強制プッシュを禁止できます。これらはリポジトリの設定であり、Gitの普遍的な動作ではありません。
1. 先に確認し、リモートのデフォルトブランチから始める
現在位置と未完了の変更がないかを確認します。
git status --short --branch
git branch --show-current
git remote -v
git remote show originでリモートが通知するデフォルトブランチを確認するか、リポジトリのページで確認します。以下ではmainを例にします。
現在の作業ブランチやファイルを変更せず、リモートの更新を取得します。
git fetch origin --prune
git log --oneline --decorate --graph -20 --all
最新のリモート・デフォルトブランチから、目的を絞った作業ブランチを作ります。
git switch --create feature/login-timeout origin/main
git fetchはリモート追跡参照を更新します。一方、git pullはまず取得してから現在のブランチへ統合するため、引数なしのgit pullは設定に応じてマージまたはリベースを行います。先に取得して調べれば、この境界が明確になります。
2. レビューしやすい変更を作る
1つのブランチでは1つの問題だけを扱います。コミット前に、作業ツリーの差分とステージ済みの差分を分けて確認します。
git status --short
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
同じファイルに関連する編集と無関係な編集が混在するとき、git add --patchが役立ちます。プロジェクト所定のフォーマッター、テスト、セキュリティチェックも実行してください。これらのコマンドはリポジトリごとに異なり、Gitから推測はできません。
ベースブランチに対してプルリクエストに何が含まれるかを確認します。
git fetch origin
git diff --stat origin/main...HEAD
git diff origin/main...HEAD
git log --oneline origin/main..HEAD
三点リーダーの差分は、2つのブランチ先端のマージベースから比較します。通常はプルリクエスト画面に表示される変更と対応します。
3. 作業ブランチを公開してレビューを依頼する
デフォルトブランチではなく、作業ブランチをプッシュします。
git push --set-upstream origin feature/login-timeout
プルリクエストまたはマージリクエストには次を書きます。
- 問題と対象範囲
- 実施したテストと結果
- 運用上または移行上のリスク
- 挙動の確認に役立つスクリーンショットやログ
- 該当する場合は関連Issueへのリンク
レビュアーは説明だけでなく、現在の差分を確認する必要があります。変更要求に対応して関係するチェックを再実行し、最終的な統合はリポジトリに設定されたマージ方式と権限に従います。
4. 統合方針を一つ選ぶ
マージ、リベース、スカッシュマージは異なる目的を持ちます。その場で無秩序に切り替えず、リポジトリ単位でチーム方針を決めます。
| 方法 | 動作 | 適切な境界 | 主な注意点 |
|---|---|---|---|
| マージ | 2つの履歴を結合し、マージコミットを作る場合がある | 共有ブランチ、またはブランチ構造を意図的に記録するリポジトリ | 機械的に使うと不要なマージコミットが増えることがある |
| リベース | 新しい基点へコミットを再生し、新しいコミットIDを作る | チーム方針が許し、他の人がまだ依存していない自分の作業ブランチ | 共有ブランチの書き換えは他の人の作業基盤を無効にし得る |
| スカッシュマージ | プルリクエストをデフォルトブランチ上の1コミットとして統合する | 中間コミットに長期的な価値がない小さな変更 | 作業ブランチ上の個別コミット境界はターゲットに残らない |
作業ブランチを書き換えずに、最新のmainを取り込む場合はマージします。
git fetch origin
git switch feature/login-timeout
git merge origin/main
チームが許可し、自分だけが使う未共有の作業ブランチである場合に限り、最新のmainへリベースします。
git fetch origin
git switch feature/login-timeout
git rebase origin/main
git push --force-with-lease origin feature/login-timeout
--force-with-leaseは予想したリモート状態を確認するため、無条件の--forceより安全ですが、それでも履歴の書き換えです。使用前に調整し、保護されたデフォルトブランチには決して使わず、他の人がその作業ブランチを利用している可能性がある場合も避けてください。
5. 衝突を意図的に解決する
マージやリベースが衝突で停止しても、衝突マーカーを機械的に消してはいけません。まず未解決のパスをすべて確認します。
git status
git diff --name-only --diff-filter=U
各ファイルを意図した最終状態に編集し、<<<<<<<、=======、>>>>>>>を取り除き、関係するテストを実行してから解決結果をステージします。
マージの場合:
git add path/to/resolved-file
git merge --continue
リベースの場合:
git add path/to/resolved-file
git rebase --continue
統合方法の選択が誤りだった場合や、解決結果に確信を持てない場合は、操作前の状態へ戻します。
git merge --abort
リベース中の場合:
git rebase --abort
2つの中止コマンドは、対応する操作の進行中だけ使用できます。
6. 共有履歴を書き換えずに復旧する
状態に合う、最も破壊性の低い道具を使います。
| 状況 | 先に確認するもの | より安全な復旧方法 |
|---|---|---|
| パスを誤ってステージした | git diff --cached -- path/to/file | git restore --staged path/to/file |
| パスの未ステージ作業ツリー編集を破棄したい | git diff -- path/to/file | git restore --worktree path/to/file |
| 誤ったコミットをすでに共有した | git show <commit> | git revert <commit>で逆変更のコミットを作り、レビューする |
| ローカルコミットを見失った | git reflog | git branch rescue-work <commit> |
分離HEAD上でコミットした | git statusとgit log -1 | 移動前にgit switch --create rescue-workを実行する |
git restore --worktreeは指定パスの未コミット内容を破棄します。必要な内容は先に別の場所へコピーしてください。git revertは新しいコミットを記録するため、共有履歴を維持します。reflogはローカルかつ保存期間に限りがある記録で、永続的なバックアップではありません。目的のコミットを見つけたら、すぐに救出ブランチを作ります。
git reset --hard、無条件のgit push --force、ブランチ削除を通常のトラブル対処として使わないでください。到達可能な作業を失ったり、共同作業者の履歴を書き換えたりする可能性があります。
7. よくある共同作業の問題を診断する
non-fast-forwardとしてプッシュを拒否された
人または自動処理がリモートブランチを進めています。強制プッシュで上書きせず、取得して確認します。
git fetch origin
git status --short --branch
git log --oneline --left-right --graph HEAD...origin/feature/login-timeout
その後、ブランチの所有関係とチーム方針に従ってマージかリベースを選びます。予想外のコミットが自分のものでなければ、その作者と調整してください。
「ブランチとoriginが分岐した」
これは双方に相手側にはないコミットが存在するという意味で、マージとリベースのどちらが正しいかまでは示しません。履歴グラフを調べ、コミットと作者を特定してから、合意した統合方針を使います。
分離したHEAD
分離状態での調査は有効ですが、新しいコミットにはブランチ名がありません。作業を残す場合は、移動前にブランチへ接続します。
git switch --create rescue-detached-work
承認後にプルリクエストが変わった
新しい差分を確認し、必須チェックを再実行します。ホスティング側のルールは古い承認を無効にしたり、最新プッシュへの承認を要求したりできます。以前の承認が後のコミットにも適用されるとは考えないでください。
繰り返し使える最小ワークフロー
git status --short --branch
git fetch origin --prune
git switch --create feature/login-timeout origin/main
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
git diff origin/main...HEAD
git push --set-upstream origin feature/login-timeout
ブランチ作成後に編集してリポジトリ固有のチェックを実行し、プッシュ後にプルリクエストを開きます。その後はレビュー、必須チェック、リポジトリのマージ方針に従います。これは出発点にすぎません。リポジトリのCONTRIBUTINGファイル、リリース手順、アクセス制御、インシデント対応手順の代わりにはなりません。
---
2019年の原エクスポート(一字一句保存)
アーカイブ境界:以下は
out/posts/2019-04-20-git-version-control-team-development-1865/index.mdにあるpost 1865の完全な本文で、エクスポート内容の日付は2019年4月20日です。表現、誤記、コマンド、ブランチ名、当時の主張は修正していません。メンテナンス版の手順として実行しないでください。
Pull before edit and push you code
git pull
View your current branch
git branch
Create and switch to created branch
git branch branchname
git checkout branchname
Merge, delete and push your code to server
git checkout master + git merge branchname
git branch -d branchname
git push origin branchname
---
