はじめに
このシリーズの Step 0・1 では、ツールのソースと文書を Git で管理してきました。第8回の振り返りでも触れたとおり、プログラムそのものより、Git などの道具でつまずくことが多くありました。
この番外編では、実際に出会った6つのつまずきを、そのときの表示と、確かめ方、直し方のセットでまとめます。どれも、気づけば数分で直せるものでしたが、最初に見たときは何が起きているのかわかりませんでした。同じところでつまずいた方の参考になればうれしいです。
作業は、自宅サーバー(Linux)に VS Code の Remote-SSH でつなぎ、VS Code のターミナルで行っています。リポジトリはツールごとに作り、GitHub の非公開リポジトリに送っています。
Git の基本の流れ
つまずきの話の前に、Git で変更を記録して送るまでの流れを確認しておきます。この流れのどこで何が起きたかがわかると、つまずきの原因も見えやすくなります。

| 操作 | 何をするか | 組み込みでいうと |
|---|---|---|
| 保存(Ctrl + S) | エディタの内容をディスク上のファイルに書き出す | エディタのバッファをディスクに書き出す |
git add | 次の記録に入れるファイルを選ぶ(ステージに登録する) | 出荷候補のリストに載せる |
git commit | 選んだ変更を、説明文を付けて手元のリポジトリに記録する | 手元で版を確定する |
git push | 手元の記録を GitHub に送る | 構成管理サーバーに登録する |
git tag | 特定の記録に名前の目印を付ける | 出荷した版にラベルを付ける |
状態を確かめるコマンドも、よく使うものは3つだけです。
| コマンド | わかること |
|---|---|
git status | 変更されたファイル、まだ記録していないファイルの一覧 |
git log --oneline | 記録の履歴を1行ずつ。GitHub に送り済みの位置には origin/main と表示される |
git diff | 記録した状態から、どこが変わったか |
以下のつまずきは、ほとんどがこの表の「保存」「git add」「git push」のどこかで起きていました。
つまずき1:初期のブランチ名が master だった
何が起きたか
新しいツールのフォルダで git init を実行したところ、長いヒントが表示されました(一部を省略しています)。
$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: will change to "main" in Git 3.0. To configure the initial branch name
hint: to use in all of your new repositories, which will suppress this warning,
hint: call:
hint:
hint: git config --global init.defaultBranch <name>
…
Initialized empty Git repository in /home/devuser/apps/unitconv/.git/一見エラーのようですが、最後の行の Initialized empty Git repository が成功の印で、リポジトリは正しく作られていました。
原因
Git では、作業の流れをブランチ(枝)と呼びます。最初に作られるブランチの名前が、今のバージョンでは master ですが、将来は main に変わる予定なので、「どちらにするか決めておいてください」と知らせてくれていたのです。GitHub も、新しいリポジトリでは main を標準にしています。
直し方
まだ何も記録していない状態なら、名前の変更は簡単です。今後のリポジトリの初期値も main にしておきます。
$ git config --global init.defaultBranch main # 今後の git init は main で始まる
$ git branch -m main # このリポジトリのブランチ名を main に変更
$ git statusgit status の1行目が On branch main になれば完了です。--global は、このユーザーのすべてのリポジトリに効く設定という意味です。組み込みでいえば、プロジェクト共通のビルド設定にあたります。
つまずき2:日本語のファイル名が数字の列になった
何が起きたか
設計書(docs/02_設計.md)を作って git status を実行すると、ファイル名が次のように表示されました。
Untracked files:
(use "git add <file>..." to include in what will be committed)
"docs/02_\350\250\255\350\250\210.md"原因
ファイルが壊れたわけではありません。Git は初期設定では、ASCII 以外の文字(日本語など)を、8進数のバイト値で表示します。\350\250\255 が「設」の UTF-8 の3バイト、\350\250\210 が「計」の3バイトです。組み込みでいえば、文字を表示する代わりに、メモリダンプでバイト列を見せている状態です。
直し方
次の設定で、日本語のまま表示されるようになります。
$ git config --global core.quotepath false
$ git statusUntracked files:
(use "git add <file>..." to include in what will be committed)
docs/02_設計.mdファイル名に日本語を使う予定があるなら、最初に設定しておくのがおすすめです。
つまずき3:空のファイルをコミットしていた
何が起きたか
設計書をコミットした後、別の作業でコミットしようとしたところ、触っていないはずの設計書が「変更あり」になっていました。そこで、その2つのコミットの間で、設計書がどう変わったかを調べました。
$ git diff 8b7c94b 2ff362c -- docs/02_設計.mdgit diff <前のコミット> <後のコミット> -- <ファイル> で、2つの記録の間の差分を、ファイルを指定して表示できます。コミットの番号は、git log --oneline の左端に出ている英数字です。
diff --git a/docs/02_設計.md b/docs/02_設計.md
index e69de29..3a4dfd7 100644
--- a/docs/02_設計.md
+++ b/docs/02_設計.md
@@ -0,0 +1,82 @@
+# unitconv 設計書
…原因
index e69de29..3a4dfd7 の e69de29 は、Git で「空のファイル」を表す決まった番号です。つまり、最初のコミットの時点では、設計書は空のまま記録されていたことになります。@@ -0,0 +1,82 @@ も、「0行だったものが82行になった」という意味です。
VS Code でファイルを作り、内容を貼り付けたものの、保存する前にコミットしていたのが原因でした。組み込みでいえば、エディタのバッファをディスクに書き出し忘れたまま、ビルドしてしまったような状況です。
確かめ方
同じことがほかのファイルで起きていないかは、記録されたファイルの大きさで確かめられます。
$ git ls-tree -l HEAD docs/100644 blob 9f0dece038e62cea9813c95506746dbd9962f131 1963 docs/01_要件定義.md
100644 blob 3a4dfd7485df76c232242557270a38e628cd8b9a 3655 docs/02_設計.md4列目の数字がファイルの大きさ(バイト数)です。0 のファイルがあれば、空のまま記録されています。
防ぎ方
今回は、後のコミットで中身が入ったので実害はありませんでした。それからは、コミットの前に次の2つを見る習慣にしています。
- VS Code のタブに、未保存の印(●)が付いていないか
git statusで、今回のコミットに入れるファイルの一覧が想定どおりか

なお、git diff の結果が長いと、画面の最後に : と出て止まります。これは1画面ずつ表示する「ページ送り」の待ち状態で、スペースキーで次へ、q キーで終了できます。
つまずき4:コミットし忘れて、別の変更と混ざりかけた
何が起きたか
画面の見た目(CSS)を整えて、index.html だけを変更したつもりでコミットしようとしたところ、git status に、触っていないはずの main.ts も出ていました。
$ git status
Changes not staged for commit:
modified: index.html
modified: src/main.ts原因を調べる
最後のコミットと、main.ts の変更内容を確かめました。
$ git log --oneline -3
$ git diff src/main.tsb95a8ff (HEAD -> main, origin/main) 入力に応じて換算結果を表示
f03b4cf 換算テーブルと計算関数を追加
0b44c7e 画面の部品を配置最新のコミットが「入力に応じて換算結果を表示」のままでした。その次の作業(入力チェックの追加)で、動作確認が終わった後に、コミットを忘れていたのです。動作確認の後に質問のやり取りが続き、コミットの手順が埋もれてしまったのが原因でした。git diff には、入力チェックの追加分がそのまま出ていました。
直し方:ファイルを指定して、目的ごとにコミットする
git add . でまとめて登録すると、2つの作業が1つのコミットに混ざってしまいます。そこで、ファイルを指定して、目的ごとに分けて記録しました。
$ git add src/main.ts
$ git commit -m "入力チェックを追加"
$ git add index.html
$ git commit -m "見た目を整えスマホに対応"
$ git push$ git log --oneline -3
1ac5cad (HEAD -> main, origin/main) 見た目を整えスマホに対応
4a03460 入力チェックを追加
b95a8ff 入力に応じて換算結果を表示1つのコミットに1つの目的、という形にしておくと、後から「いつ何を変えたか」を追いやすくなります。組み込みで、変更票を1件ずつ切るのと同じ考え方です。
防ぎ方
動作確認が OK になったら、次の話題に移る前にコミットする。これを習慣にしました。質問したくなったときも、先にコミットしておけば、どこまで終わったかが履歴に残ります。
逆に、先にコミットしてあったのに、もう一度 git commit を実行すると、次のように表示されます。
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean「記録すべき変更は何もない」という意味で、害はありません。git log --oneline -1 で、目的のコミットがすでにあるかを確かめれば十分です。
つまずき5:リポジトリ名を後から直す
何が起きたか
GitHub のリポジトリ名は、ツールが増えても見分けやすいように「apps-<ツール名>」という規則にしていました。ところが、push のときの表示を見ると、送り先が規則と違う名前になっていました。
To https://github.com/example-user/unitconv.git
8b7c94b..2ff362c main -> main正しくは apps-unitconv です。リポジトリを作るときに、規則を確かめ忘れていました。
直し方
名前の変更は、GitHub 側と手元の両方で行います。
① GitHub でリポジトリ名を変える(ブラウザで操作)
- GitHub でリポジトリを開き、「Settings」タブを開く
- 「Repository name」を新しい名前に変える
- 「〜 is available.」と表示されたら、「Rename」を押す
② 手元の送り先を書き換える
$ git remote set-url origin https://github.com/example-user/apps-unitconv.git
$ git remote -v
$ git pushorigin https://github.com/example-user/apps-unitconv.git (fetch)
origin https://github.com/example-user/apps-unitconv.git (push)
Everything up-to-dategit remote は、送り先(リモート)の設定を扱うコマンドです。origin は、送り先に付けた呼び名です。Everything up-to-date は「送るべき新しい記録はない」という意味で、新しい名前の送り先に正しくつながったことの確認になります。
GitHub は、名前を変えると古い名前からも自動で転送してくれます。それでも、送り先は正式な名前に直しておくほうが、後で混乱しません。
防ぎ方
リポジトリ名に限らず、名前の規則は、ものが少ないうちにそろえるのが楽です。名前の規則は「決定事項」の文書に書いてあるので、新しいツールを始めるときは、そこを確かめてからリポジトリを作るのが確実です。
つまずき6:push で認証エラーになった
何が起きたか
それまで問題なく送れていた git push が、突然次のようなエラーになりました。
$ git push
Missing or invalid credentials.
Error: connect ECONNREFUSED /run/user/1000/vscode-git-c10dfc6893.sock
…
remote: Repository not found.
fatal: Authentication failed for 'https://github.com/example-user/apps-unitconv.git/'少し前にリポジトリ名を変えていたので、それが原因のようにも見えます。
原因
このシリーズでは、サーバーに鍵を置かず、GitHub の認証を VS Code に任せています。git が push するときは、VS Code が用意した「認証の窓口」(vscode-git-….sock というソケット)に「パスワードをください」と問い合わせます。
エラーの ECONNREFUSED は、その窓口につながらなかったという意味です。VS Code が再接続や再読み込みをして窓口が作り直されたのに、開きっぱなしのターミナルが、古い窓口の住所を覚えたままになっていたのが原因でした。組み込みでいえば、デバイスをリセットした後も、古いハンドルを握ったままアクセスしようとしている状態です。
Repository not found(リポジトリが見つからない)も、名前の変更とは関係ありません。GitHub は、認証できない相手には、非公開リポジトリの存在そのものを隠すため、「見つからない」と返すのです。
直し方
まず、記録自体は手元に残っていることを確かめます。
$ git log --oneline -1f03b4cf (HEAD -> main) 換算テーブルと計算関数を追加origin/main が付いていないのは、「手元にはあるが、まだ GitHub には届いていない」という意味です。記録は消えていないので、慌てる必要はありません。
次に、VS Code のターミナルを閉じて(ターミナルパネル右上のごみ箱アイコン)、Ctrl + Shift + ` で新しいターミナルを開き、もう一度 push します。新しいターミナルは、VS Code の今の窓口の住所を受け取ります。
$ cd ~/apps/unitconv
$ git push
$ git log --oneline -1To https://github.com/example-user/apps-unitconv.git
0b44c7e..f03b4cf main -> main
f03b4cf (HEAD -> main, origin/main) 換算テーブルと計算関数を追加origin/main が付けば、GitHub まで届いています。それでも失敗する場合は、VS Code で F1 を押して「Developer: Reload Window」を実行してから、ターミナルを開き直すと直ることがあります。
おまけ:タグの種類をそろえる
つまずきではありませんが、Step の区切りに付けたタグ(目印)にも、知っておくとよいことがありました。
タグは2種類ある
| 種類 | 中身 | 作り方 |
|---|---|---|
| 軽量タグ | 記録への目印だけ | git tag 名前 |
| 注釈付きタグ | 目印に加えて、作成者・日時・説明文を持つ | git tag -a 名前 -m "説明" |
Step 1 のタグを付けるとき、Step 0 で付けたタグと種類をそろえたかったので、まず Step 0 のタグを調べました。
$ git -C ~/apps/hello cat-file -t step0-donecommitgit -C <フォルダ> は、そのフォルダに移動せずに git を実行する指定、cat-file -t は、指定したものの種類を表示する指定です。結果が commit なら軽量タグ(記録を直接指している)、tag なら注釈付きタグです。組み込みでいえば、メモリダンプの前に、そのアドレスにあるのがコードかデータかを確かめるようなものです。
タグを付けて送る
Step 0 が軽量タグだったので、Step 1 もそろえました。タグは、通常の git push では送られないので、名前を指定して送ります。
$ git tag step1-done
$ git push origin step1-done
$ git log --oneline -131a0802 (HEAD -> main, tag: step1-done, origin/main) 振り返りを記録tag: step1-done が付けば完了です。出荷したファームに版番号のラベルを付けておくのと同じで、いつでもその時点の状態を取り出せます。
まとめ:コミットの前のチェックリスト
6つのつまずきから、コミットと push の前に確かめることを、チェックリストにまとめました。
| タイミング | 確かめること | 防げるつまずき |
|---|---|---|
| 最初に1回 | init.defaultBranch main と core.quotepath false を設定した | 1、2 |
| リポジトリを作るとき | 名前が決めた規則どおりか | 5 |
| コミットの前 | VS Code のタブに未保存の印(●)がない | 3 |
| コミットの前 | git status の一覧が、今回の作業のファイルだけ | 3、4 |
| コミットの前 | 違う目的の変更が混ざっていれば、ファイルを指定して分けて git add | 4 |
| 動作確認の後 | 次の話題に移る前にコミットした | 4 |
| push の後 | git log --oneline -1 に origin/main が付いた | 6 |
| push が失敗したら | ターミナルを開き直す(記録は手元に残っている) | 6 |
振り返ると、つまずきの多くは「確かめずに次へ進んだ」ことが原因でした。組み込みで、書き込む前にベリファイし、リリースの前に差分を確認してきたのと同じで、Git でも、1つの操作ごとに git status や git log で状態を確かめる習慣が、いちばんの予防策だと感じています。
この番外編は、第8回の振り返りの補足です。シリーズは、次の Step 2(計算 API)に進みます。
この記事は、シリーズ「組み込みエンジニアの Web 開発入門」の1本です。ほかの回は、シリーズの目次からどうぞ。



コメント