おもこん

おもこんは「思いつくままにコンピュターの話し」の省略形です

Jekyllを勉強中(4)

作成したGitHubのレポジトリをローカルにクローンして、Jekyllでテストすることを説明します。 あわせて、Gitについても簡単に触れます。 GitはJekyllに限らず、開発では必須のアプリです。

Gitについて

GitHubはその名の通り、Git(バージョン管理アプリ)+Hub(中心、ネットワークの経由地)です。 すなわち、Gitレポジトリを複数のユーザが共有するためのハブです。 したがって、GitHubを活用してウェブページを作成する上で、Gitは極めて重要です。 まだ使ったことのない人は、この機会に使い方を覚えましょう。 すでにGitに慣れている人は、Gitの説明の部分を飛ばして構いません。

インストール

Linuxではディストリビューションにパッケージがあります。 Ubuntuならば、

$ sudo apt install git

で簡単にインストールできます。

Windowsの場合はGitのホームページから、「Downloads」をクリックしてダウンロードページに行き、Windows版のインストーラをダウンロードします。 あとはインストーラの指示に従ってインストールします。

Gitの使い方

Gitのすべてを説明するには紙面が足りませんので、主な使い方を説明します。

初期設定

Gitにユーザ名とメールアドレスを登録します。

$ git config --global user.name "ユーザー名"
$ git config --global user.email "メールアドレス"

ユーザ名に空白がある場合、例えば「Taro Yamada」のような場合、ダブルクォートで囲む必要があります。 これは、Bashが空白を引数の区切りと解釈するためです。 なお、ユーザ名は本要でなくても構いません。 Gitのレポジトリの中でコミットした人を識別するために使われます。 また、そのレポジトリをGitHubに公開するとその名前も公開されることになります。

GItでコミットするときにエディタが必要になりますが、その設定は

$ git config --global core.editor エディタ名

です。 Ubuntuではこの設定をしないとデフォルトとしてnanoが使われます。

GitHubのレポジトリのクローン

前回作ったGitHubのレポジトリをローカル(自分の使っているパソコン)にコピーしましょう。

  • ブラウザでGitHubにアクセスする。 サインイン(ログインのこと)していない場合は、「Sign in」をクリックして、サインインする。
  • 画面右上のアイコンをクリックし、現れたポップアップメニューから「Your repositories」をクリックする
  • 前回作成したレポジトリ名をクリックする

ここまでで、レポジトリが表示されます。 ここで、緑色のボタン「Code」をクリックし、ポップアップメニューの四角が斜めに重なっているアイコン(コピーを示すアイコン)をクリックします。 私の「Jekyll-tutorial-for-beginners」の画面で赤い丸で囲まれたところがアイコンです。

レポジトリとコピーアイコン

クリックしても何も目に見える変化はありませんが、実はパソコンのクリップボードにレポジトリのアドレスがコピーされています。

  • 端末(Windowsではコマンドプロンプト、以下は「端末」と表示)から、「git clone (クリップボードをペースト)」と入力する。 クリップボードからペーストするには、Linuxでは「Shift+Ctrl+V」を、Windowsでは「Ctrl+V」を押す。 Windowsで上手く行かない場合は、コマンドプロンプトの設定ができていない可能性がある。 「コマンドプロンプトでコピペ」でグーグル検索するとやり方がヒットしますので、参照してください。 私のレポジトリをクローンする場合はコピペの結果「git clone https://github.com/ToshioCP/jekyll-tutorial-for-beginners.git」となります。
  • エンターキーを押すと、レポジトリがコピーされる。 レポジトリ名のディレクトリがクローンされたレポジトリ。 ディレクトリを開くと「README.md」と「_config.yml」が入っているはず。

うまくクローンできたでしょうか? 良くわからない場合は「git clone」でネットを検索すると解説サイトが見つかると思います。

レポジトリの状態確認

端末のカレントディレクトリをクローンされたレポジトリに移動します。 レポジトリの状態を確認するには次のようにタイプします。

$ git status
ブランチ main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
  • 「status」は状態、状況のこと。
  • ブランチについては、ここでは知らなくても大丈夫です。 後で必要が生じたら説明しますが、おそらく使わないでしょう。 操作の対象となっているのが「main」(というブランチ)だということが、表示されている。
  • 次の英語は「ブランチは'origin/main'(これはGitHubのレポジトリのこと)とともに、最新にアップデートされています」という意味。
  • 最後の行は「(新たな)コミットはなし。ワークツリーには何も(新しいことが)無し」ということだが、若干説明を加える。 ワークツリーはこのディレクトリ(これを作業ディレクトリともいう)のこと。 例えば、このディレクトリに新しいファイルを作ることは「ワークツリーに新規ファイルを作成」することになる。 その後に「git status」すれば表示は当然変わってくる。

Jekyllをローカルで使う

クローンされたレポジトリでJekyllを動かしてみましょう。 ローカルで動かすためにはいくつか準備が必要です。

Gemfileの追加

Gemfileはそのレポジトリで使うRubyのライブラリを記述します。 「gem」(ジェム)は英語で宝石のことです。 Rubyの用語では、「gem」はRubyのライブラリを指します。 さらに、

  • ライブラリであるgemをまとめたRubygemsからライブラリをダウンロードするコマンドも「gem」。 例えば「gem install jekyll」とすると、jekyllをダウンロードできる。 gemではなくbundlerというコマンドを使うことも多い。 ただ、それはgemが必要なくなったということではない。 gemとbundlerでは動作が違うので状況で使い分ける。
  • Rubygemsとパッケージ管理の全体を指して「gem」ということもある。

Gemfileの記述では、必要なライブラリ名を「gem」の後に続けます。

source "https://rubygems.org"

gem "jekyll-theme-leap-day"
gem "webrick"
  • 最初の行はライブラリをRubygemsから取得するという意味。
  • テーマの「jekyll-theme-leap-day」のgemを入れると、「jekyll」もインストールされるので、「gem jekyll」を書かなくても良い。
  • webrick」はJekyllがローカルでウェブサーバとしてレポジトリのサイトを配信するために使われるライブラリ。 現在(2022/8/14)の最新バージョンのRubyではgemをインストールしなければならない。

Gemfileを記述したら、Bundlerでインストールをします。 BundlerはRuby2.6.0から標準添付されているので、特にインストールの必要はありません。

$ bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Using public_suffix 4.0.7
Using bundler 2.3.16
... ... ...
... ... ...

Using jekyll-theme-leap-day 0.2.0
Bundle complete! 3 Gemfile dependencies, 31 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
$

「bundle」はBundlerを端末から起動するためのコマンド名です。 「install」はgemをインストールするサブコマンドです。 BundlerはGemfileから、記述されているgemが依存するgemとそのバージョンをすべて調べ、「Gemfile.lock」というファイルに書き出します。 さらに、それらすべてをインストールします。 「Gemfile.lock」に書かれたバージョンのgemを起動するには「bundle exec」コマンドを使います。 例えば「bundle exec jekyll serve」のようになります。 「bundle exec」なしで「jekyll serve」としないでください。 もしそうすると「Gemfile.lock」とは無関係にjekyllを起動することになるので

  • JekyllをBundlerなしでインストール(例えば「gem install jekyll」など)していなければJekyllを起動できない
  • バージョンの違うJekyllが起動される可能性がある

したがって、レポジトリ内では常に「bundle exec」をつけてgemを起動するようにしてください。

index.mdの作成

README.mdはGitHub pagesではブラウザで表示されましたが、ローカルでは同じように表示されません。 それに、そもそもREADME.mdはレポジトリ(GitHub Pagesではない)のトップ画面でレポジトリそのものを説明するためのものです。 それに対してGitHub Pagesのトップページはレポジトリとは別に作られたスペースにおける「index.html」になります。

JekyllはMarkdownをHTMLに変換してくれるので、index.htmlを直接書かずMarkdownのindex.mdを書けば十分です。 私のレポジトリ用のindex.mdを例として示しておきます。 なお、index.mdはレポジトリのトップディレクトリに置きます。

---
layout: default
title: Jekyll tutorial for beginners
---
# jekyll-tutorial-for-beginners
Jekyll is a framework for static web sites. This repository provides a tutorial in the GitHub page.

# Under Construction

This repository contains Jekyll source files for the GitHub page.

The contents of the page is a Jekyll tutorial for beginners.

But it is NOT completed yet.
  • 3つの-の行で囲まれた部分はフロント・マター(書物の前付--書籍の本文の前に入れる序文、目次などの総称)という。 そこには、yaml形式でそのファイルの情報を書く。 「キー: 値」はハッシュ(連想配列)を表す。 区切りにはコロン(:)と半角空白を入れる。 空白は省略できない。
  • 「layout」はその文書のレイアウトを表すファイルを指す。 defaultはレポジトリ内にはないが、テーマのgemで提供されている。
  • 「title」はこの記事のタイトルで、レイアウトによって使われる。 通常は、ブラウザのタグに現れるタイトルにしたり、表示画面の最初に<h1>などを使って表示したりする。

フロントマターを除いた部分は本体、またはコンテンツと呼ばれます。 ここはマークダウンで記述します。

なお、フロントマターが無いファイルについてはJekyllは何もせずにそのまま出力ページにコピーします。 フロントマターに記述する内容が無くても、MarkdownをHTMLにしたければフロントマターが必要です。 その際は、---を2行書いておくだけで大丈夫です。

_config.ymlの変更

Readme.mdは出力ページに生成する必要がなく、またすべきではありません。 その場合は、_config.ymlの中にexcludeオプションで生成対象から除外します。 このオプションではyamlのリスト(配列)を使います。

theme: jekyll-theme-leap-day

exclude:
  - README.md

リストは-と半角空白で表します。 たとえば

- abc
- def
- ghi

は3つの要素からなるリストです。 -の後の半角空白を省略することはできません。 このリストはRubyのデータ構造では配列になります。

[ "abc", "def", "ghi" ]

と同じことです。 _config.ymlでは、ハッシュ「exclude」の値がリストになっています。 そのときは、リストはハッシュに対してインデント(半角空白で字下げ)をしなければなりません。 このときタブを用いることはできず、かならず半角空白を用います。 空白の字数は1つ以上であればいくつでも構いませんが、見やすさの点から2文字程度にするのが一般的です。

_config.ymlをRubyのデータ構造で表すと、

{ "theme" => "jekyll-theme-leap-day" }
{ "exclude" => [ " README.md" ] }

となります。 これで、README.mdはHTMLに生成されません。

Jekyllで確認

Jekyllを起動してブラウザで画面を確認しましょう。

$ bundle exec jekyll serve
Configuration file: /home/toshio/MYWEBSITE/jekyll-tutorial-for-beginners/_config.yml
            Source: /home/toshio/MYWEBSITE/jekyll-tutorial-for-beginners
       Destination: /home/toshio/MYWEBSITE/jekyll-tutorial-for-beginners/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
                    done in 0.129 seconds.
 Auto-regeneration: enabled for '/home/toshio/MYWEBSITE/jekyll-tutorial-for-beginners'
    Server address: http://127.0.0.1:4000
  Server running... press ctrl-c to stop.

ここでブラウザを立ち上げ、「localhost:4000」を開きます。 すると、レポジトリから作られた画面が表示されます。 私のPCでは次のように表示されました。

Jekyll tutorial for beginners -- local

確認できたら、端末から「CTRL-C」を入力してJekyllのサービスを停止させます。

index.mdのコンテンツの部分は白い背景になっている中央部分に表示されています。 その周りの部分はレイアウトが自動的に書いてくれています。

  • 最上段のタイトルは、フロントマターのタイトルがコピーされている
  • コンテンツ左のリンクはMakdownの見出しへのリンクになっている。

このように、テーマのレイアウトは自動的にタイトルやリンクを生成してくれるのでサイト構築が楽になります。

_siteディレクト

レポジトリを再確認すると、新しいディレクトリ「_site」ができています。

$ tree
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── _config.yml
├── _site
│   ├── assets
│   │   ├── css
... ... ...
... ... ...
│   └── index.html
└── index.md

6 directories, 34 files

Jekyllは「_site」ディレクトリを生成します。 この生成のタイミングは

  • 「bundle exec jekyll serve」の直後、サービスが動いている間は、index.mdなどのファイル(_config.ymlを除く)が更新されるごと
  • 「bundle exec jekyll build」で_siteを生成するとき

です。 生成時には、まず「_site」の中身を全て削除してから生成します。 うっかりして「_site」の中にファイルを作ったりすると、生成時に失くなってしまいます。

ブラウザには「_site」の中身が表示されます。 つまり、このディレクトリがウェブサービスのページを格納しているディレクトリなのです。 Jekyllは「レポジトリのファイルからページを組み立ててこのディレクトリに書き出す」ということをしていたわけです。

もし、レンタル・サーバーなどのウェブスペースを持っている場合は、この中身をアップロードすればウェブページが公開できます。

Gitでよく使う操作(status, add, commit, push)

ワークツリーの状態確認

ワークツリーに変更を加えたので、GItで状態の確認をしましょう。

$ git status
ブランチ main
Your branch is up to date with 'origin/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:   _config.yml

追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)
        .jekyll-cache/
        Gemfile
        Gemfile.lock
        _site/
        index.md

no changes added to commit (use "git add" and/or "git commit -a")

いろいろ表示されていますが、ここで注目したいのは「Changes not staged for commit(コミットのためにステージされていない変更)」と「追跡されていないファイル」のところにあるファイルです。 Gitはバージョン管理ツールで、最後にコミットされた時点までの情報を隠れフォルダ「.git」に保存しています。 クローン元のGitHubのレポジトリではどのようなコミットをしていたでしょうか?

  • README.mdを作成した。これが最初のコミット
  • 「jekyll-theme-leap-day」のテーマをセットした。 これは設定画面でテーマを設定したときにGitHub側で(自動的に)コミットしてくれています。

クローンした後、

  • Gemfileを追加した
  • 「bundle install」でGemfile.lockが追加された
  • _config.ymlを変更した
  • index.mdを追加した
  • Jekyllを起動したときに_siteと.jekyll-cacheディレクトリができた

これらが「git status」で表示されているファイルなのです。

ここまでの仕事をGitを使って記録しましょう。 ここで考えなければならないのは、すべて記録しておくべきだろうか、ということです。

  • Gemfileは必要なgemの記述だから記録する
  • Gemfile.lockはGemfileのgemだけでなく、実行に必要なすべてのgemとそのバージョンを記述しているので記録する
  • _config.ymlは記録する
  • index.mdは記録する
  • _siteと.jekyll-cacheはJekyllが生成したフォルダで、Jekyllの起動に必要なわけではない。これは記録しない。
.gitignore

記録しないファイルは「.gitignore」というファイルに記述します。 それにより、Gitはそれらのファイルを記録対象から外します。 エディタで次のように書き、「.gitignore」という名前で保存します。 ファイル名の先頭がドット(.)です。 忘れないようにしてください。

# Cache directory
.jekyll-cache

# HTML directory created by Jekyll
_site

一般的にGitで記録すべきでないファイルは

  • 生成されたファイル、生成途中で作られる中間ファイル
  • テキストファイルのバックアップファイル。たとえば「index.md~」のようにティルダのつくもの。

です。 再度「git status」してみましょう。

$ git status
ブランチ main
Your branch is up to date with 'origin/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:   _config.yml

追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        Gemfile
        Gemfile.lock
        index.md

no changes added to commit (use "git add" and/or "git commit -a")

.gitignoreに書かれたファイルが表示されなくなりました。

git add

ここに表示されたファイルはGitで記録に残すようにします。 そのための手順がさきほどの画面に出ています。

  (use "git add <file>..." to update what will be committed)
  (use "git add <file>..." to include in what will be committed)

この2行から、「git add <file>」とコマンド入力することによって、アップデート(変更)とインクルード(追加)ができる、ということが分かります。 全てのファイルをaddするには、カレントディレクトリ「.」をaddすれば良いので、

$ git add .

とタイプします。 このコマンドで変更されたファイルと追加されたファイルがステージの状態になります。 この状態ではまだGItに記録されたわけではありません。 記録の準備の段階が完了したということです。 再び状況確認します。

$ git status
ブランチ main
Your branch is up to date with 'origin/main'.

コミット予定の変更点:
  (use "git restore --staged <file>..." to unstage)
        new file:   .gitignore
        new file:   Gemfile
        new file:   Gemfile.lock
        modified:   _config.yml
        new file:   index.md

記録すべきファイルがすべて「コミット予定の変更点」に書かれています。 このことは、ファイルがステージに登録されたということです。 なお、ステージに誤ってファイルを入れてしまった場合はアンステージ(ステージから除くこと)できます。

  (use "git restore --staged <file>..." to unstage)

「git restore --staged <file>」でアンステージできると書かれています。 このように、Gitは親切で、そのときに使えるコマンド(の主なもの)が表示されます。

git commit

ステージされたファイルを記録に残すことをコミットといいます。 英語のコミット(commit)にはいろいろな意味がありますが、その中に「(物事を)(記憶・焼却など)にゆだねる、付す」という意味があります。

commit an idea to writing => 着想を書き留める

「git commit」コマンドでファイルを記録し、メモを残すことができます。 コマンドを発行すると、エディタが立ち上がるので、短くメモを書きます。 例えば「Add Gemfile and index.md.」などです。 上書き保存します。 上書き保存後に下のようにメッセージが表示されます。

$ git commit
[main a516afb] Add Gemfile and index.md.
 5 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 .gitignore
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock
 create mode 100644 index.md
  • mainブランチのa516afb(から始まる)IDに「Add Gemfile and index.md.」というメッセージをつけて保存した
  • ファイルが5つ変更され、103行が追加され1行が削除された(実際には_config.ymlで4行追加したのですが、1行削除されて5行追加されたようにgitが認識しています)。
  • 各ファイルがモード100644(オーナーのみ読み書き可、グループと一般ユーザは読みのみ可)で記録された

このように、Gitにはファイルの内容だけでなくモードも記録されます。

$ git status
ブランチ main
このブランチは 'origin/main' よりも1コミット進んでいます。
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Git の状態は、ローカルがorigin/main(GitHubのレポジトリ)よりも1コミット進んでいる、と表示されました。 先程のコミットの分だけローカルのほうが進んでいるわけです。 ワークツリーは(最後のコミットから)特に変更無くクリーンでコミットするようなものはない、と表示されています。

git push

さきほどの表示に

  (use "git push" to publish your local commits)

とありました。 「git push」を使ってローカルのコミットを(GitHubに)公開できる。 ということです。 ローカルに対してGitHubはリモートといいます。 ローカルからリモートに新たなコミットをコピーするのが「git push」です。 逆にリモートが進んでいるときは「git pull」を使ってローカルに取り込みます。 大事なことは、コミットしたものだけがプッシュされることです。 コミットしていないワークツリーはプッシュしないので、必ずコミットしてください。

GitHubにpushするには、いくつかの方法がありますが、ここではパーソナル・アクセス・トークン(PAT)を使うことにします。 PATはパスワードのようなものですが、パスワードよりは強力なものです。

  • GitHubを開く
  • 右上のアイコンをクリック=>ポップアップメニューからSettingsをクリック
  • 左のメニューの一番下「Developer settings」をクリック=>「personal access tokens」をクリック
  • 「Generate new token」をクリック=>パスワードを入力する=>以下画面に従ってトークンを生成する
  • 生成されたトークンをメモしておく。またはエディタでファイルに保存しておく。

トークンは今後毎回pushで使います。 ユーザ名とパスワードを要求されますが、パスワードにはPATを入力します。

$ git push
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.50 KiB | 1.50 MiB/s, done.
Total 7 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/ToshioCP/jekyll-tutorial-for-beginners.git
   4901be1..a516afb  main -> main

これでGitHub Pagesの方もindex.mdが表示されるようになっているはずです。 自分のレポジトリのページを見たところ見た目では確認できませんでした。 それもそのはずで、index.mdの内容はREADM.mdをコピーしたものだから、同じに見えるのはあたりまえだったのです。 少しでも代えておけば・・・残念。

ローカルでテスト、リモートで公開

ここまでで、ローカルとリモートを同じ状態に保つことができるようになり、しかもローカルでJekyllを使ってテストできるようになりました。 今後は

  • ローカルでウェブサイトの内容を作っていく
  • ローカルでJekyllを使ってテストする
  • コミット
  • GitHubにプッシュ=>公開

という手順で開発をすることができます。

最後にGitの参考ページのリンクを付けておきます。