Git入門:バージョン管理のきほん
変更を記録する(add と commit)
このレッスンで分かること
git addとgit commitを分けて実行する具体的な手順- コミットが 1 つ増えると
git logの表示がどう変わるかaddを忘れた、余計なファイルをaddした、というときの戻し方
前提を 30 秒で確認する
前のレッスンで扱った通り、ファイルはワークツリー・ステージ・リポジトリの 3 か所を移動します。git add がワークツリーからステージへ、git commit がステージからリポジトリへ運ぶ操作です。
プレーンテキスト
ワークツリー --git add--> ステージ --git commit--> リポジトリ冒頭の図解にある通り、コミットは 1 つずつ鎖のようにつながって履歴になります。このレッスンでは、その鎖の最初の 3 つを実際に作ります。
作業は前レッスンで作った git-practice フォルダで続けます。
ターミナル
cd ~/git-practice
git statusプレーンテキスト
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)README.md が未追跡のまま残っている状態から始めます。無い場合は作り直してください。
ターミナル
echo "# Git practice" > README.mdgit add でステージに乗せる
ファイル名を指定してステージに乗せます。
ターミナル
git add README.mdこのコマンドは成功しても何も表示しません。Git は成功時に黙るコマンドが多く、これは正常な動作です。結果を確かめるには git status を使います。
ターミナル
git statusプレーンテキスト
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.mdさきほどまで Untracked files にいた README.md が Changes to be committed に移りました。この見出しが「ステージにあるもの」を意味します。new file は、リポジトリにまだ存在しない新規ファイルだという表示です。
複数のファイルをまとめて乗せることもできます。
| 書き方 | 対象 |
|---|---|
git add README.md | そのファイル 1 つ |
git add README.md index.html | 指定した複数ファイル |
git add src/ | そのディレクトリ配下すべて |
git add . | 今いるディレクトリ配下すべて |
git add -A | リポジトリ全体すべて |
git add . は便利ですが、意図しないファイルまで巻き込みます。実行前に必ず git status で何が変更されているかを見る癖を付けてください。特にパスワードを書いた設定ファイルや、サイズの大きい生成物を誤ってコミットする事故は、ほぼ git add . から起きます。
git addは「追加」という語感ですが、実際には「今のこの内容をステージに写す」操作です。すでに追跡しているファイルを編集したときもgit addを使います。新規と更新で別のコマンドがあるわけではありません。
ここで押さえておきたいのが、git add はその瞬間の内容を写すという点です。git add したあとにもう一度そのファイルを編集すると、ステージには古い内容、ワークツリーには新しい内容が入った状態になります。git status では同じファイル名が Changes to be committed と Changes not staged for commit の両方に出ます。
プレーンテキスト
Changes to be committed:
modified: README.md
Changes not staged for commit:
modified: README.mdこの状態でコミットすると、記録されるのはステージにある古いほうです。「直したはずの修正が入っていない」という混乱の正体はこれです。編集したら git add をやり直す、と覚えておけば防げます。
git commit で履歴に刻む
ステージに乗ったものを記録します。
ターミナル
git commit -m "初回コミット"プレーンテキスト
[main (root-commit) 8f3d2a1] 初回コミット
1 file changed, 1 insertion(+)
create mode 100644 README.md-m はメッセージをその場で指定するオプションです。付けない場合はエディタが開き、そこにメッセージを書いて保存・終了するとコミットされます。
出力の読み方は次の通りです。main は今いるブランチ名、root-commit は履歴の 1 件目であることを示す印、8f3d2a1 がこのコミットのIDです。1 file changed, 1 insertion(+) は 1 ファイルに 1 行追加されたという集計です。
もう一度 git status を見ます。
ターミナル
git statusプレーンテキスト
On branch main
nothing to commit, working tree cleannothing to commit, working tree clean は、ワークツリーとステージとリポジトリの 3 つが完全に一致している状態を表します。この表示が出ていれば、記録されていない変更は 1 つもありません。作業の区切りでこの状態を作るのが基本の進め方です。
履歴を確認します。
ターミナル
git log --onelineプレーンテキスト
8f3d2a1 (HEAD -> main) 初回コミットHEAD -> main は「今いる場所が main ブランチで、その先端がこのコミット」という意味です。git log の詳しい読み方は次々回のレッスンで扱います。
2 つめ、3 つめのコミットを積む
ファイルを 1 つ増やし、既存のファイルも編集して、変更が 2 種類ある状態を作ります。
ターミナル
echo "console.log('hello');" > app.js
echo "Git の練習用リポジトリです。" >> README.md
git statusプレーンテキスト
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
app.js
no changes added to commit (use "git add" and/or "git commit -a")見出しが 2 つに分かれました。Changes not staged for commit は追跡済みだが編集されただけのファイル、Untracked files はまだ一度も記録していないファイルです。
ここで 2 つを別々のコミットにしてみます。まず app.js だけを記録します。
ターミナル
git add app.js
git commit -m "hello を出力するスクリプトを追加"プレーンテキスト
[main 4b7e903] hello を出力するスクリプトを追加
1 file changed, 1 insertion(+)
create mode 100644 app.js続いて README.md を記録します。
ターミナル
git add README.md
git commit -m "README にリポジトリの説明を追記"プレーンテキスト
[main c1a5f22] README にリポジトリの説明を追記
1 file changed, 1 insertion(+)2 件目以降には root-commit の表示が付きません。親コミットを持つ普通のコミットだからです。
ターミナル
git log --onelineプレーンテキスト
c1a5f22 (HEAD -> main) README にリポジトリの説明を追記
4b7e903 hello を出力するスクリプトを追加
8f3d2a1 初回コミット新しいものが上に並びます。冒頭の図解と同じ形で、3 つのコミットが鎖になりました。
追跡済みファイルの編集だけをコミットしたいときは
git commit -am "メッセージ"でaddを省略できます。ただし未追跡ファイルは対象外なので、新規ファイルは含まれません。この落とし穴があるため、慣れるまではaddとcommitを分けて打つことを勧めます。
メッセージの書き方の最低限
コミットメッセージには決まった正解がありませんが、最初に守るべき点は 3 つです。
1 つめは、何をしたかを書くことです。「修正」「更新」だけでは 1 週間後の自分に何も伝わりません。「ログインボタンが押せない不具合を修正」まで書きます。
2 つめは、1 行目を 50 文字程度に収めることです。多くのツールが 1 行目だけを一覧に表示するため、長いと途中で切れます。詳しい説明が要るときは、1 行空けてから 2 行目以降に書きます。
3 つめは、日本語で書いて構わないということです。チームの方針が英語でない限り、正確に伝わるほうが優先されます。
よく見かける形として、先頭に種類を示す短い語を置く書き方があります。
| 先頭の語 | 使う場面 |
|---|---|
feat | 新しい機能を足した |
fix | 不具合を直した |
docs | ドキュメントだけを直した |
refactor | 動きは変えずに書き方を整えた |
test | テストを足した、直した |
この書き方に従うと fix: ログインボタンが押せない不具合を修正 のようになります。慣習として広く使われているので、他人のリポジトリを読むときに知っておくと役に立ちます。個人の練習では必須ではありません。
複数行のメッセージは -m を重ねて書けます。
ターミナル
git commit -m "検索フォームの入力チェックを追加" -m "空文字と全角スペースだけの入力を弾くようにした。既存の検索処理には影響しない。"書き方の詳細は第 2 章の良いコミットメッセージの書き方で扱います。
ありがちな失敗と戻し方
add を忘れてコミットした
git add を打たずに git commit すると、Git は記録するものが無いと言って止まります。
プレーンテキスト
On branch main
Changes not staged for commit:
modified: README.md
no changes added to commitこのメッセージが出たら、単に git add を打ってからやり直せば済みます。何も壊れていません。
厄介なのは、複数ファイルを直したのに 1 つしか add していない場合です。コミットは成功しますが、中身が欠けています。出力の 1 file changed が期待と違ったら、その場で気付けます。忘れたファイルを追加して git commit --amend で直前のコミットに含める方法が第 2 章にあります。
余計なファイルを add した
まだコミットしていないなら、ステージから降ろすだけで済みます。
ターミナル
git restore --staged secret.txtこのコマンドはステージから外すだけで、ワークツリーの中身には触れません。ファイルが消えることはないので安心して実行できます。
git status の案内には git rm --cached と出ることもあります。こちらは未追跡の状態に戻す操作で、新規ファイルをステージから外す場合はどちらでも同じ結果になります。
変更を全部消したくなった
編集内容そのものを捨てて、最後のコミットの状態に戻したい場合は次を使います。
ターミナル
git restore README.mdこれは編集内容を消す操作なので、実行すると元に戻せません。まだコミットしていない変更は Git のどこにも残っていないからです。実行前に本当に捨ててよいか確認します。詳しい挙動は第 2 章の変更を取り消す(restore)で扱います。
次のレッスンでは git status と git diff を使い、いま何がどう変わっているのかを正確に読む方法を身につけます。この 2 つが読めるようになると、add する前に中身を確認できるので事故が激減します。
git addはステージに写す操作、git commitはステージの内容を履歴に刻む操作git commit -mの出力に出る1 file changedは、意図した数と合っているか毎回確認するnothing to commit, working tree cleanは 3 か所が一致している安全な状態- ステージから降ろすのは
git restore --staged、編集を捨てるのはgit restore