3-3. コンフリクト・rebase・stash・.gitignore
このセクションで学ぶこと
Section titled “このセクションで学ぶこと”3-1・3-2 で基本操作とチーム開発フローを学んだ。このセクションでは、実務でほぼ毎日遭遇する「詰まりやすいポイント」を集中して扱う。
1. コンフリクト(衝突)
Section titled “1. コンフリクト(衝突)”なぜ起きるのか
Section titled “なぜ起きるのか”2 つの branch が同じファイルの同じ行を別々に変更した状態で merge しようとすると、Git はどちらを正解とすべきか判断できない。これがコンフリクトである。
main branch : price = 1000;feature branch : price = 1200;
→ merge しようとすると Git が「どちらを使う?」と止まるコンフリクトマーカーの読み方
Section titled “コンフリクトマーカーの読み方”コンフリクトが起きたファイルには、自動的に次の記号が挿入される。
<<<<<<< HEADprice = 1000; ← HEAD(マージ先)の内容=======price = 1200; ← マージしようとしている branch の内容>>>>>>> feature/pricing<<<<<<< HEADから=======まで:現在いる branch(merge 先)の変更=======から>>>>>>>まで:merge しようとした branch の変更
1. git status でコンフリクト中のファイルを確認する → "both modified" と表示される
2. コンフリクトファイルをエディタで開く
3. マーカーを削除し、正しい内容だけを残す (どちらか一方・両方採用・書き直しなど)
4. git add <file> ← 解消済みとしてステージ
5. git commit ← マージコミットを完成させる例:解消後のバリエーション
// 変更前(コンフリクト中)<<<<<<< HEADprice = 1000;=======price = 1200;>>>>>>> feature/pricing
// ① feature の値を採用する場合price = 1200;
// ② main の値を採用する場合price = 1000;
// ③ どちらでもなく書き直す場合price = 1100; // 両者の議論で決めた別の値
// ④ 両方を残す場合(コード内容による)const BASE_PRICE = 1000;const NEW_PRICE = 1200;コンフリクトを減らすには
Section titled “コンフリクトを減らすには”- branch の生存期間を短くする(長期間放置すると差分が積もる)
- 1 つの branch では関心の近いファイルだけ変更する
- こまめに main の最新を取り込む(後述の rebase や
git merge main)
2. rebase
Section titled “2. rebase”merge との違い
Section titled “merge との違い”【merge】 main: A - B - C - - - M ← M がマージコミット \ / feature: D - E
グラフに分岐・合流が残る。履歴は正確だが複雑になりやすい。
【rebase】 main: A - B - C ← main の先端 feature: D'- E' ← D, E を C の上に"付け替え"る
グラフが一直線になる。feature の commit は書き直されるのでHash が変わることに注意。基本コマンド
Section titled “基本コマンド”# feature branch で作業中に main を取り込みたいときgit switch maingit pull # まず main を最新状態にするgit switch feature/my-featuregit rebase mainこれで「feature/my-feature の commit が main の先端から始まったかのように」歴史が書き換えられる。
rebase 中にコンフリクトが起きた場合
Section titled “rebase 中にコンフリクトが起きた場合”# コンフリクト発生 → 解消 → 続行git rebase main# → CONFLICT と表示されたら# → ファイルを手動編集して解消git add <conflicted-file>git rebase --continue
# やり直したいときgit rebase --abortインタラクティブ rebase — 直前 n commit を整理する
Section titled “インタラクティブ rebase — 直前 n commit を整理する”git rebase -i HEAD~3 # 直前 3 commit を操作するエディタが開き、次のような一覧が出る。
pick a1b2c3 Add price validationpick d4e5f6 Fix typopick g7h8i9 Update price validation
# コマンド例# pick = そのまま残す# squash = 直前 commit にまとめる(メッセージ編集あり)# fixup = 直前 commit にまとめる(メッセージ不要)# reword = コミットメッセージだけ変える# drop = この commit を消すこれにより「作業中の細かい commit を PR 前に 1 つにまとめる」「誤字 commit を消す」などが可能になる。
rebase の黄金律
Section titled “rebase の黄金律”すでに push した(共有済みの)commit を rebase してはいけない
rebase は commit の Hash を書き換えるため、同じ branch を持っている他の人の履歴と食い違いが起き、強制 push が必要になる。 ローカルのみの branch に対して使うのが基本である。
3. git stash
Section titled “3. git stash”「feature branch で作業中に、別の緊急修正 branch へ切り替えなければならないが、作業が中途半端でコミットできない」というとき、git stash で変更を一時退避できる。
作業中の状態(commit できない) ↓ git stash退避されてキレイな状態 ↓ 別 branch へ切り替え・作業 ↓ 元の branch に戻る ↓ git stash pop作業中の状態が復元される主なコマンド
Section titled “主なコマンド”# 変更を退避する(メッセージあり版が後で分かりやすい)git stash push -m "価格バリデーション実装途中"
# 一覧を見るgit stash list# stash@{0}: On feature/pricing: 価格バリデーション実装途中# stash@{1}: On main: 別の退避
# 最新の退避を戻す(リストから削除)git stash pop
# 特定の退避を戻す(リストから削除せず)git stash apply stash@{1}
# 特定の退避を削除するgit stash drop stash@{1}
# 全退避を削除するgit stash clearstash の注意点
Section titled “stash の注意点”- 追跡されていない新規ファイルは
git stashだけでは含まれない →-uオプションで untracked も含める:git stash push -u -m "メッセージ" stash pop時にコンフリクトが起きることがある → 通常のコンフリクト解消と同じ手順
4. .gitignore
Section titled “4. .gitignore”.gitignore はリポジトリのルートに置くテキストファイルで、「Git で追跡しないファイル・ディレクトリ」を指定する。
よく除外するもの
Section titled “よく除外するもの”| 種類 | パターン例 | 理由 |
|---|---|---|
| ビルド成果物 | dist/, build/, *.class | 毎回生成できるため |
| パッケージ | node_modules/, .gradle/ | インストールで再現できる |
| 環境変数・秘密情報 | .env, .env.local | 漏洩防止 |
| OS・エディタの自動生成 | .DS_Store, Thumbs.db, .vscode/ | 不要なノイズ |
| ログ | *.log, logs/ | 大量かつ不要 |
# コメントnode_modules/ # ディレクトリごと除外(末尾 / はディレクトリを示す)*.log # 拡張子で除外.env # ファイル名で除外!important.log # ! で除外のキャンセル(このファイルだけ追跡する)/dist # ルート直下の dist だけsrc/**/*.tmp # src 以下の全 .tmp ファイルすでに追跡中のファイルを除外したいとき
Section titled “すでに追跡中のファイルを除外したいとき”# .gitignore に追加しても、すでに track されているファイルは無視されない# 追跡を外す(ファイル自体は残す)git rm --cached .env
# ディレクトリごと追跡を外すgit rm -r --cached node_modules/
# その後 .gitignore に追加して commit するグローバル .gitignore(全リポジトリ共通)
Section titled “グローバル .gitignore(全リポジトリ共通)”.DS_Store や .vscode/ など、特定 OS・エディタ由来のファイルは個人の好みによるため、リポジトリの .gitignore より自分の環境専用ファイルに書くほうが望ましい。
# グローバル gitignore の設定git config --global core.excludesfile ~/.gitignore_global~/.gitignore_global に書く内容の例:
.DS_StoreThumbs.db.vscode/*.swp| 機能 | 主な使い場面 | 注意点 |
|---|---|---|
| コンフリクト解消 | 同じ行を別々の branch が変更した後の merge | マーカーを必ず全部消す |
git rebase | 直線的な履歴にする・PR 前の整理 | 共有済み commit には使わない |
git rebase -i | commit をまとめる・メッセージを直す | ローカル branch のみに限定 |
git stash | 作業途中で branch を切り替えたい | untracked は -u が必要 |
.gitignore | 生成物・秘密情報を除外する | 追跡済みは git rm --cached が先 |
次のステップ
Section titled “次のステップ”- 3-3. 演習問題
- 第3章を終えたら、4-1. 変数・型・制御フロー・関数 へ進もう。