変更要約: 初版
1.4バージョン管理とGit
Gitによるバージョン管理の利点と、clone・add・commit・push/pull・branch・mergeの役割、そしてマージ競合の解決と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 diffやgit log -pでunified 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行のマーカーをすべて消して統合しないと壊れたファイルが残ります。
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の解釈として最も適切なものはどれか。

