Instiq
第1章 · ソフトウェア開発と設計·v1.0.0·更新 2026/7/20·読了目安 約16分

変更要約: 初版

1.4バージョン管理とGit

この節の要点

Gitによるバージョン管理の利点と、cloneaddcommitpush/pullbranchmergeの役割、そしてマージ競合の解決とunified diff@@ハンクと+/-行)の読み方を、「このgit出力は何を意味し、次に何をするか」という提示物の解釈・診断として学びます。

インフラをコードで扱う(IaC)時代、設定やスクリプトはGitで版管理するのが前提です。試験でも実務でも問われるのは「コマンド名の暗記」より、目の前のgit出力を読んで次の一手を決める力——push が拒否された理由、競合マーカーの意味、diff が示す変更内容を正しく解釈できるかです。この節では、まずGit(分散型)の利点と基本コマンドの役割を押さえ、次にマージ競合の解決手順とunified diffの読み方を、実際の出力を診断する形で学びます。

1.4.1バージョン管理の利点

  • Git分散型バージョン管理:各開発者が全履歴を持つローカルリポジトリで作業し、任意の時点へ戻せる。誰が・いつ・なぜ変更したかが履歴に残り、壊れたら直前のコミットへ復旧できる——これが手作業運用に対する最大の安全網。
  • ブランチで本流(例:main)から分岐して安全に開発し、完成後にマージで統合できる。複数人が並行して別機能を進めても衝突を管理でき、レビュー(pull request)や自動テストをマージ前に挟める。IaCでは設定変更の履歴と巻き戻しが特に効く。

1.4.2基本コマンドの役割

  • git clone <url>=リモートリポジトリを丸ごと複製してローカルに取得。git add <file>=変更をステージング(次のコミットに含める印付け)。git commit -m "..."=ステージした変更をローカル履歴に記録(この時点ではまだリモートに反映されない)。
  • git push=ローカルのコミットをリモートへ送るgit pull=リモートの変更を取得して自分の作業に統合(fetch+merge)。git branch/git checkout -b=ブランチの作成/切替。git rm=追跡ファイルの削除を記録。順序の型は変更→add→commit→(pullで最新化)→push

1.4.3マージ競合とdiffの読み方

  • マージ競合は、同じ行を別々に変更したブランチを統合したときに起きる。Gitは競合箇所を<<<<<<< HEAD=>>>>>>> branchで囲んで示す。上側が自分(HEAD)側、下側が相手ブランチ側の内容で、人間がどちらを採るか(または統合するか)を決めてマーカーを消し、addしてcommitする。
  • unified diffは変更を-(削除行)と+(追加行)で示し、@@ -10,3 +10,4 @@のようなハンクヘッダが変更位置(旧10行目から3行/新10行目から4行)を表す。git diffで作業ツリーの差分、git logで履歴を確認する。diffを読めれば「このコミットは何を変えたか」をレビューで即断できる。
試験ポイント

「add=ステージ・commit=ローカル記録・push=リモート送信・pull=取得+統合」「competeマーカー<<<<<<< HEAD/=/>>>>>>>の上=自分・下=相手」「unified diffは-削除/+追加・@@が位置」「push拒否(non-fast-forward)はまずpull」が頻出。設問は「このgit出力の意味は」「次に打つべきコマンドは」の解釈型で来ます。

あなたが機能ブランチで作業を終えgit pushすると、リモートから! [rejected] ... (non-fast-forward)hint: Updates were rejected because the remote contains work that you do not have locally.が返りました。ここで力任せにgit push --forceするのは危険な判断です——同僚のコミットを上書きして履歴を壊しかねません。正しい読みは「リモートに自分がまだ持っていない変更がある=先に取り込め」で、次の一手はgit pull(fetch+merge)です。pullすると今度は、同じ設定ファイルの同じ行を双方が変更していたためマージ競合が起き、該当箇所がこう表示されました:<<<<<<< HEAD / timeout = 30 / = / timeout = 60 / >>>>>>> origin/main。上のブロック(HEAD)は自分の変更(30)、下のブロックは相手の変更(60)です。ここでやるべきは、どちらの値が正しいかをチームの意図に照らして決め、マーカー3行(<<<<<<<=>>>>>>>)をすべて削除して1つの正しい行に統合し、git add <file>でステージ、git commitで競合解決を記録、最後にgit pushすることです。競合解決後、git diffgit log -punified diffを見ると、@@ -12,1 +12,1 @@のハンクに- timeout = 30+ timeout = 60が並び、「12行目の値を30から60へ変えた」ことが一目で読めます。ここで大事なのは、rejectedや競合マーカーをエラーとして怯えるのではなく、「リモートが先行→pullして統合→競合は人が決めてマーカー除去→add/commit/push」という決まった手順の入口として読む判断です。diffの+/-@@を正しく読めれば、レビューで「この変更は何をどう変えたか」を即座に説明できます。

コマンド/記号意味典型の使いどき
clone / pull複製 / 取得+統合(fetch+merge)初回取得 / 作業前の最新化
add / commitステージ / ローカル履歴に記録変更を確定して記録する
pushローカルのコミットをリモートへ記録後に共有する
branch / merge分岐 / 統合並行開発と合流
<<< === >>> / +,-,@@競合マーカー / diffの追加削除・位置競合解決とレビュー
注意

ひっかけ: push がnon-fast-forwardで拒否されたとき「git push --forceで押し込む」は誤りです——同僚のコミットを消しかねません。正しくは先にgit pullして統合します。また「git commitすればリモートにも反映される」も誤り=commitはローカル履歴への記録で、共有にはpushが必要です。競合マーカー=は区切りで、3行のマーカーをすべて消して統合しないと壊れたファイルが残ります。

Gitの基本コマンドとマージ競合・unified diffの読み方の図。
git出力を読み次の一手を決める

1.4.4この節のまとめ

  • Gitは分散型で全履歴を持ち任意時点へ復旧できる。branchで並行開発しmergeで統合、マージ前にレビュー/テストを挟める
  • 順序の型は変更→add(ステージ)→commit(ローカル記録)→pull(最新化)→push(リモート送信)。commitだけではリモートに反映されない
  • push拒否(non-fast-forward)はまずpullマージ競合は3行のマーカーを消して統合しadd/commit、unified diff-削除/+追加・@@が位置

進捗の記録にはログインが必要です。

理解度チェック

(軽い確認用)

Q1. 機能ブランチで`git push`すると`! [rejected] ... (non-fast-forward)`と「リモートに自分がまだ持っていない変更がある」旨のヒントが返った。履歴を壊さずに進める次の一手として最も適切なものはどれか。

Q2. 設定ファイルをマージした際、競合箇所が`<<<<<<< HEAD` / `timeout = 30` / `=======` / `timeout = 60` / `>>>>>>> origin/main`と表示された。この出力の解釈と正しい解決手順として最も適切なものはどれか。

Q3. あるコミットの`git diff`出力に`@@ -12,1 +12,1 @@`というハンクヘッダの下に`- timeout = 30`と`+ timeout = 60`が並んでいた。このunified diffの解釈として最も適切なものはどれか。

理解度を確認第1章「ソフトウェア開発と設計」の問題を解く