フォークとは
GitHubのヘルプページには、こうある。
フォークは、リポジトリのコピーです。
リポジトリをフォークすると、元のプロジェクトに影響を与えずに自由に変更を試すことができます。最も一般的には、フォークは他人のプロジェクトへの変更を提案するか、
他人のプロジェクトを自分のアイデアの出発点として使用するために使用されます。
↓を見ると、もう少しざっくりとイメージすることができるかも。
https://qiita.com/matsubox/items/09904e4c51e6bc267990
お断り
- GitHubを使っていることが前提の話です。
- あくまで自分の経験でのやり方に尽きるので、これやって現場で怒られても責任は持てません。。
- 通常Git初心者は(他の人から勧められて)GUIツールを使うと思いますが、この記事では基本的にコマンドでの説明になるのでTortoiseGitの使い方も期待している方の期待には沿えません。
お題
Gitは難しい。
いや、実際に使って、何度か失敗して、本やネットで最低限使うコマンドや概念をちょっとずつ覚えていった後なら、それほどでもないと言える。
「言える」というのは「ちゃんと理解している」という意味ではない。
職場で『なんも理解してないな、こいつ』と思われているほどの酷いレベルではないという意味。
自分が職場でGitを初めて使ったのは5年前くらいかな。
ただ、その現場はエンジニアの半分以上が「Gitビギナー」だったので、自分が知らなくても、失敗しても、ほとんどの人が同じように知識がなく、失敗していたので、相対的に問題視されなかった。
でも、今はわりと、「Gitさわったことない」ってエンジニアはレアなんじゃないかと思う。
もちろん、エンジニアと言ったって何を専門としていたかによる部分はあるし、ガラパゴス的な職場に長年いたとしたら、そういうこともあるのかもしれない。
けど、そういう人が「モダン(と言うと気に障る人がいるかもしれないけど)」な現場に来ると、けっこうツラい思いをする。
実際、ここ2〜3年の間にお邪魔した現場では軒並みそうして苦しんでいる人が一人はいたから。
じゃあ、Git の何にそんなに苦しむのかと言うと、Git だけの話じゃないから。
(自分がお邪魔する現場の特色かもしれないけど)大抵、ソースは GitHub のプライベートリポジトリで管理していた。
(まれに、社内(ないしクラウド)に GitLab サーバを構築して管理しているところもあった。)
そして、現場に新しいエンジニアが入ってくると、おおよそこんなようなニュアンスのことを言われる。
「メンバーに登録するから、GitHubのアカウント教えて!」
そう、ここ最近は、GitHubのアカウントは持っていることが前提で聞かれることが多い。
とはいえ、個人のアカウントなので、それをそのまま使うか、その職場で付与された職場用のメールアドレスでもって新しくアカウント作るかは要確認。
さて、GitHubのアカウントを作って、それを伝えると、表題のセリフが飛んでくる。
これも、実は現場によりけりで、必ずしもフォークを求められない現場もあった。
けど、今回は表題の(どちらかというと手間の多い)手順の方について書こうと思う。
表題に「新人ではないが」と書いたのは、新人ならとにかく何も知らないなら何も知らないことを伝えて、やり方を一から聞けばいいから。
新人でなくても、異常にコミュニケーション能力が高くて、苦もなく情報を引き出せる人なら問題ない。
が、そうでない人は多い。(自分もそう)
なので、最低限『なんも理解してないな、こいつ』と思われない程度には、作業できるようになっておきたい。
そんな人向け。
と、偉そうに書いておきながらだけど、そうは言っても所詮は自分が経験してきた限られた現場での話に過ぎないので、ここに書いたことがどこでも通用するかと言ったら、・・・通用しないかもしれない。
悪しからず。
自分も結局、最初は、いつも現場の雰囲気、温度感、レベル感、何をどの程度気にする人が多いのか、いろんな空気を読みつつ作業をはじめる。
残念ながら、「これをやっておけば大丈夫」という、きれいにテンプレート化された現場は今のところ一つもなかったから。
作業環境
# OS
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
通常は作業端末自体がLinuxということは少ない気がするのだけど、今自分が使っているのはLinuxなので。。。
# Git
$ git version
git version 2.17.1
今時点で最新は「2.20.1
」のようだけど、今回のように基本的な使い方を挙げるだけなら差は生じないはず。
本題
長い前置きを経て、本題。
自分のGitHubアカウントでログインして指定された別アカウントのリポジトリをフォーク
1) 自分のGitHubアカウント(例:「your-own-account
」)でログイン中
2) 指定された別アカウント(例:「sky0621
」)のリポジトリ(例:「productA
」)をフォーク
すると、このように自分のアカウントのものとしてリポジトリが出来上がる。
このリポジトリは、指定された別アカウント「sky0621
」のリポジトリとは別のものなので、(フォーク元としての結びつきはあるものの)ローカル環境で自分が修正した内容を仮にこのリポジトリ(your-own-account/productA
)に反映したとしても、それだけではフォーク元(sky0621/productA
)には一切反映されない。
3) 現在位置
今時点の状態を把握。gitなりGitHubを使っている場合、とにかく今どういう状態なのか、常に意識する(ないし確認できる状態にしておく)ことが大事。
はい。今は、まだ github.com 上の世界だけです。ローカルは一切関係ありません。
とにかく、github.com 上にある「sky0621
」アカウントの「productA
」リポジトリを自分の作業アカウントである「your-own-account
」の「productA
」リポジトリとしてフォークしただけです。
フォークしたリポジトリを自分のローカル環境にクローン
ここからは、コンソール開いてGitコマンドばしばし打っていくことになります。
自分のGitHubアカウント(例:「your-own-account
」)にフォークしたリポジトリ(productA
)のコピーをローカルに持ってきます。
【前提】
・Gitはローカル環境にインストール済み
【重要】
・ローカル環境のどのディレクトリ内でソース管理するかを決めておく!
※わりと何も考えないと、自分のホームディレクトリ直下に「work
」なんてディレクトリ作って、その下に「github.com/【自分の作業アカウント名】
」といった構造で掘っておく。
※正直なところ、開発で使う言語によってソース管理すべきパスが変わったりするかもしれない。そのへんは言語別のガイド参照。
あらかじめ↓でcloneするURLをコピーしておく。
コンソール開いて、ソース管理するディレクトリに移動してgit clone
$ cd /home/xxxx/github.com/sky1456second/
$ pwd
/home/xxxx/github.com/sky1456second
$
$ git clone https://github.com/your-own-account/productA.git
Cloning into 'productA'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 7 (delta 1), reused 2 (delta 0), pack-reused 0
Unpacking objects: 100% (7/7), done.
$
$ cd productA/
$ ls -l
合計 8
-rw-r--r-- 1 sky0621 sky0621 16 2月 13 14:36 README.md
-rw-r--r-- 1 sky0621 sky0621 4 2月 13 14:36 a.txt
$
$ git branch
* master
これで、ローカル環境に「productA
」リポジトリのソースが持ってこれた。
このソースを修正して、ローカル上で動作確認して、それを最終的に「sky0621(実プロダクト管理アカウント)
」の「productAリポジトリ
」に反映するところまで出来れば、いったんは作業完了と言える。
再び、現在位置を確認
「local環境」の枠が増えた。もう、この時点で1つのリポジトリが3箇所に登場する事態に。
勝手な想像だけど、”GitHubでフォーク方式でソース管理する”ということで既に舞台が3つ出てくることを明確に意識しないで作業すると、のちのちハマるんじゃないかと思う。
大事なのは、local環境にも「リポジトリ」が作られたということ
※「リポジトリ」は、そのプロジェクトが作成されてから現在に至るまでの全てのリビジョン(=ソースの変更履歴)を記録しているデータベース。
つまり、この時点で、ローカル環境でもソースのバージョン管理ができるようになったということ。
このローカル環境のリポジトリは、自分だけのものなので、たとえ、コンパイルすら出来ない状態のソースを反映したとしても、まったく問題なし。
ローカル環境の状態を掘り下げ
上の図では実は「local環境」を端折って書いている。
端折らずに(local環境の部分だけ)詳しく書くと、こうなる。ちゃんとGitを理解している人が見るとツッコミが入るかもしれない。。。
ただ、言いたきことは、ひとえにローカル環境と言っても、↓の3つにわかれている(そして、それを意識しないといけない)ということ。
・GitHub上のリポジトリをコピーした(ローカル専用の)リポジトリ
・(ローカル専用のリポジトリとは別に存在する)作業ディレクトリ(内の実ファイル群)
・作業ディレクトリで行った変更内容を(ローカル専用の)リポジトリに反映する前の「反映したいソースの変更が出るたびに(反映候補として)乗っけておく」領域
以降、↑のイメージを元に、ソースを修正して、add -> commit -> push -> プルリク -> merge といった流れをトレースする。
ソース修正・コミット前にやること
自分とローカルリポジトリの状態をチェック
まず、これからソースを修正しようとする、先ほど git clone
して出来たディレクトリに移動
で、Git操作を行う上での自分の設定を確認。
$ git config -l
user.email=【★1】
user.name=【★2】
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=https://github.com/your-own-account/productA.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
↑の★1と★2が表示されない(たぶん最初は表示されない)場合は、以下を参考に「個人を識別可能なメールアドレスと名前」をセットする。
https://git-scm.com/book/ja/v1/使い始める-最初のGitの構成
これをしておかないと、複数人で作業している時に、「このコミット、誰がやったんだよっ!」と言う時に怒りの矛先が見つかりにくくなる。
あとは、「 remote.origin.url=https://github.com/your-own-account/productA.git
」という記述から、
このローカル環境にこさえたリポジトリが「origin
」という識別子でGitHub上のyour-own-account
アカウントのリポジトリと紐付いていることがわかる。
ちなみに、この紐付きは以下でも確認できる。
$ git remote -v
origin https://github.com/your-own-account/productA.git (fetch)
origin https://github.com/your-own-account/productA.git (push)
作業ブランチを作成
この時点でソースは修正できるのだけど、現実問題、このまま作業進めると、たぶん怒られる。
GitHubからフォークしたりクローンしたりで、どうにかこうにかローカルまでソースを落としてきたけど、その落としてきたソースには「master
ブランチ」という名前が付いている。
(非常に誤解を生む表現かもしれない。。。 あえて書いてみたけど。)
2個前の図には、しれっと「master
ブランチ」と載せていたのだけど、そう、落としてきたのは「master
ブランチ」。
先に『「リポジトリ」は、そのプロジェクトが作成されてから現在に至るまでの全てのリビジョン(=ソースの変更履歴)を記録しているデータベース』と書いた。
まあ、↓のように、何かソースを修正してリポジトリに反映したら、その全ての履歴が記録されているわけで、
[修正01] -> [修正02] -> [修正03] ...
「ブランチ」は、その中の 特定の履歴(コミットとも言う)を指す 矢印のようなもの。
う〜ん、わかりづらいか。 でも、本にも使われているんだよなぁ、「矢印」って表現。
「ブランチ」=「枝」なので、わかれることができる。
リポジトリ作ったばかりだと、 master
ブランチしかない。それだけだとある程度の規模のチーム開発になると作業しづらくなってくる。(※)
※このあたりは、git-flowやGitHub Flowと絡んできて話がどんどん広がるので止める。
なので、まずは最低限、本番リリースとは別に開発リリース用とでも言うようなブランチ「develop
ブランチ」を作る。
ただ、この作業はGit初心者には、あまり振られることはないと思うので、たぶんそういう master
とは違うブランチも大元のリポジトリには作られているはずだと思っていればいい。
(もし、無かったら、なぜ無いのか聞いてみてもいいと思う。)
というわけで、今回も「develop
ブランチ」はあるていで進める。
フォークした時にブランチも付いてくるので、フォーク元にdevelop
ブランチがあれば、フォーク先にもあらわれる。
さあ、じゃあ、このdevelop
ブランチをローカルに落としてきて作業を進めればいいのかというと、
やっぱり、たぶん、それも後ほど怒られることになる。(いや、現場によりけりだと思うけど、一応今までの現場では避ける人が多い。)
これから何かソースを修正しようというからには、その理由(きっかけ)があるはず。
「新規機能の追加」だったり「バグ修正」だったり。
チーム開発でGitを使う場合、わりとお作法として、そういう理由(「トピック
」と表現される)を表したブランチ名を付けた新しいブランチを作ってローカルで作業することが多い。(と思う。)
これも、一応現場の人に聞いてみたらいい。
「トピックブランチ(ないしフィーチャーブランチ)の命名規則はありますか?」
経験上、こんなのが多い。
「feature/【自分を特定する名前】/【ソース修正理由を簡潔に表す英単語なり英文(もしくはIssueドリブンならIssueナンバー)】
」
具体的にはこんなの。
「feature/your-own-account/fix-user-cannot-delete
」
はい。長々とブランチ作成に至るくだりを書いてきたけど、とりあえず今回は、単純に新規テキストファイルを追加するだけの改修なので、↓のようにブランチを作る。
$ git branch
* master
$
$ git checkout -b feature/your-own-account/add-btxt origin/develop
Branch 'feature/your-own-account/add-btxt' set up to track remote branch 'develop' from 'origin'.
Switched to a new branch 'feature/your-own-account/add-btxt'
$
$ git branch
* feature/your-own-account/add-btxt
master
これで、今ローカル環境で作業した場合、ソースを反映する先が「feature/your-own-account/add-btxt
」ブランチになった。
ソース修正〜GitHub反映
ここからは一気に。
ローカル環境でソース修正
修正前のローカル状態確認
今の状態は、こう。「a.txt」があるだけ。
$ ls -l
合計 8
-rw-r--r-- 1 sky0621 sky0621 16 2月 13 14:36 README.md
-rw-r--r-- 1 sky0621 sky0621 4 2月 13 14:36 a.txt
ここに「b.txt」を追加する。
が、その前に、なにはともあれ、叩くコマンドがある。
$ git status
ブランチ master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
ソースをいじる前に「nothing to commit, working tree clean」であることを確認。これ、大事。
もう1回、さっきの図を引っ張ってこよう。(なぜかインデックスだけオレンジに塗ったやつ)
↓に出てくる3つの箱、すべてが同じ状態であることを表す言葉「nothing to commit, working tree clean
」。ここがスタートライン。
ソース修正と修正後の確認
では、ソース修正、といっても、ただの空ファイル「b.txt」を追加するだけ。
(実際の業務ではありとあらゆる修正のパターンがあるだろうし、そもそもいきなり修正する前にローカルで動作確認する環境を整えたりするのだけど、今回の主題ではないので省略)
$ touch b.txt
$
$ ls -l
合計 8
-rw-r--r-- 1 sky0621 sky0621 16 2月 13 14:36 README.md
-rw-r--r-- 1 sky0621 sky0621 4 2月 13 14:36 a.txt
-rw-r--r-- 1 sky0621 sky0621 0 2月 13 23:59 b.txt
これで git 的に何が起きたかと言うと、
$ git status
ブランチ feature/your-own-account/add-btxt
Your branch is up to date with 'origin/develop'.
追跡されていないファイル:
(use "git add <file>..." to include in what will be committed)
b.txt
nothing added to commit but untracked files present (use "git add" to track)
Git は親切なので、「今、どういう状況であるか」と「どうしたらいいか」をちゃんと教えてくれる。
・どういう状況? → ローカルのリポジトリに未反映の修正が表れた!
・どうしたいい? → (リポジトリに反映したいなら)git add
するといい!
この状態を図で表すと、こう。
あくまでGit管理とは関係ない作業ディレクトリ上でだけ、「b.txt」が増えたという状態。
で、例えば、ここで、誰かに「c.txtを追加してローカルで動作確認してみて!」と言われたとする。
しかがたないので、「c.txt」を追加する。
$ touch c.txt
$
$ ls -l
合計 8
-rw-r--r-- 1 sky0621 sky0621 16 2月 13 14:36 README.md
-rw-r--r-- 1 sky0621 sky0621 4 2月 13 14:36 a.txt
-rw-r--r-- 1 sky0621 sky0621 0 2月 13 23:59 b.txt
-rw-r--r-- 1 sky0621 sky0621 0 2月 14 00:09 c.txt
で、Git 的には、こうなる。
$ git status
ブランチ feature/your-own-account/add-btxt
Your branch is up to date with 'origin/develop'.
追跡されていないファイル:
(use "git add <file>..." to include in what will be committed)
b.txt
c.txt
nothing added to commit but untracked files present (use "git add" to track)
インデックスに載せる
修正(追加)したファイルは2つ。でも、「c.txt」は他の人から言われたから追加したもので、もともと(「feature/your-own-account/add-btxt
」ブランチ用の作業として)想定したものではない。
とはいえ、「c.txt」もせっかく追加したので捨て去るわけにもいかない。
こうした時に、”インデックス”という存在が役に立つ。
ここには、載せるもの載せないものがピックアップできるので、今回のブランチ用に必要な修正分だけを載せればいい。
↓のように。
$ git add b.txt
$
$ git status
ブランチ feature/your-own-account/add-btxt
Your branch is up to date with 'origin/develop'.
コミット予定の変更点:
(use "git reset HEAD <file>..." to unstage)
new file: b.txt
追跡されていないファイル:
(use "git add <file>..." to include in what will be committed)
c.txt
これで、想定していた「b.txt」だけが「コミット予定の変更」として管理され、「c.txt」はいまだに「追跡されていないファイル」のまま、扱いがわけられた。
またまた、図的には、こうなった。
ローカルのリポジトリに反映する
ここで登場した「コミット
」という言葉。
これは、ローカルのリポジトリに変更内容を反映するということを表す。
では、やってみる。
あ、その前に、このコミットをする前は、ローカルのリポジトリにおけるこれまでの作業履歴はどうなっているのか確認。
$ git log
commit fd863219413ca1d18bfff8edeff886da48e9753e (HEAD -> feature/your-own-account/add-btxt, origin/develop)
Author: sky0621 <sky14work@gmail.com>
Date: Wed Feb 13 13:53:13 2019 +0900
a
commit cdc2ca473f0daff59d9d0e5871de83b5b1c1d01a
Author: Taro <sky14work@gmail.com>
Date: Wed Feb 13 13:49:01 2019 +0900
Initial commit
履歴が2つある状態。
それに対し、今のローカルへの変更内容をコミットするとどうなるか。
$ git commit -m "add b.txt"
[feature/your-own-account/add-btxt 2c089c7] add b.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
そして再び履歴を見てみると、見事に1件、履歴が増えている。
Author欄が先だって設定しておいた「自分を特定する」メールアドレスと名前になっていることの確認も大事!
$ git log
commit 2c089c78bfbacb2cafa8b50b8ba5bd0dbf52861b (HEAD -> feature/your-own-account/add-btxt)
Author: your-own-account <sky14ghcv@gmail.com>
Date: Thu Feb 14 00:23:43 2019 +0900
add b.txt
commit fd863219413ca1d18bfff8edeff886da48e9753e (origin/develop)
Author: sky0621 <sky14work@gmail.com>
Date: Wed Feb 13 13:53:13 2019 +0900
a
commit cdc2ca473f0daff59d9d0e5871de83b5b1c1d01a
Author: Taro <sky14work@gmail.com>
Date: Wed Feb 13 13:49:01 2019 +0900
Initial commit
図に表すと、こうなった。
ここまでで、ようやく、ローカル環境のリポジトリにおけるソース修正反映は終わり。
ローカルリポジトリの内容をGitHubの自分のアカウントのリポジトリに反映
これまでの内容は、リポジトリがあって履歴管理は出来ているものの、ローカルマシンが死んだら消えてしまうもの。
それでは困る(というか、そもそもチーム開発している上で、他の人の変更分の取り込みや、他の人にも自分の修正分が見えるようにしないと意味がない)ので、GitHubに上げる。
認証が絡んだ話
GitHubからgit clone
してきたので先述の通りGitHub上のリポジトリとの紐付けは出来ており、git push
一発で、実はGitHubに反映できる。
が、クローンしてきたら誰でもかれでも反映できるのはまずいので、当然認証がかかっている。
今から上げる先は、自分で作ったGitHub上のアカウントのはずなので、当然(?)IDとパスワードはわかっている。
これを以下に書いておくと認証を通ってgit push
できる。
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = https://github.com/your-own-account/productA.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "feature/your-own-account/add-btxt"]
remote = origin
merge = refs/heads/develop
最初にgit clone
してきた時に「.git
」というディレクトリが作られていて、その中の「config
」というファイルにGitHub上のリポジトリとの紐付けやらが書いてある。
この中の「 https://github.com/your-own-account/productA.git 」の部分を「 https://your-own-account@github.com/your-own-account/productA.git 」にする。
そして、git push
の時にパスワードを聞かれるので入力。
$ git push -u origin feature/your-own-account/add-btxt
Password for 'https://your-own-account@github.com':
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 303 bytes | 303.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'feature/your-own-account/add-btxt' on GitHub by visiting:
remote: https://github.com/your-own-account/productA/pull/new/feature/your-own-account/add-btxt
remote:
To https://github.com/your-own-account/productA.git
* [new branch] feature/your-own-account/add-btxt -> feature/your-own-account/add-btxt
Branch 'feature/your-own-account/add-btxt' set up to track remote branch 'feature/your-own-account/add-btxt' from 'origin'.
これで、実際にGitHub上で自分のアカウントのリポジトリを確認してみると、新しいブランチが出来ている。
ここまでで図としてはこうなっている。
フォーク元のリポジトリに反映
GitHub上でプルリクエストを出す。
マージ先ブランチは「develop
」にしている。今回想定した流れとしてはそうなる。
ここも、現場による部分があるかもしれないので、要確認。
プルリクエストが出来た。図で言うと、こういう状況。
GitHub上の)自分のリポジトリの「develop
」ブランチにマージする手順を踏まないのか?と言われると、「踏まない」。
登場するブランチすべてを順番に辿って反映していくことが趣旨ではない。
フォーク元の「develop
」ブランチに対してローカルで修正した内容を最終的にフォーク元の「develop
」ブランチに反映することが目的なので。
そういう意味では、修正内容をマージするための最短距離は「フォーク元のdevelop
ブランチをローカルにチェックアウトして修正し、それを直接フォーク元のdevelop
ブランチにプッシュ」になるんだけど。
それをやってしまうとチーム開発としては具合が悪い。まず、レビュー無しにソース反映されてしまう。品質を考えるなら”レビューレス”は悪手。なので、プルリクエストを出す形式を取るために直接フォーク元にプッシュはしない。
それさえ守れば、自分のトピック(フィーチャー)ブランチからフォーク元のdevelop
ブランチにプルリクエストを出すという形式がわかりやすくていいと思う。
と、ここまで書いていて、意図的に重要なことに触れていないことを白状。
「チーム開発だから、自分が修正している間に他の人も修正している。同じような箇所を直していて、プルリクエストを出した時に競合しないのか?」
しますね。可能性としてはあります。実際、何度もあります。
なので、通常は、プルリクエストを出す前に、ローカル環境であらかじめ競合を解消しておきます。
ただ、競合解消の話をはじめると、merge と rebase に触れなくてはいけなくなり、それだけで1記事ボリュームの話になるので、今回は触れません。
実際の業務ベースで発生しうることに触れずじまいで消化不良かもしれないけど、ごめんなさい。
(余力があれば、別の記事で・・・)
レビューの上、マージ
現場、状況によりけりだけど、通常はプルリクエスト出した人にはマージ権限はないので、マージ権限がある人にレビューを依頼し、結果問題がなければマージしてもらう。
今回は、フォーク元もフォーク先もどちらも自分でこさえたアカウントなので、単純にマージ先のアカウントでログインしてマージしてしまう。
マージされた。
まとめ
くどくどと書いてみたけど、やっぱり自分ももはや初心者ではないから、Git初心者がこの書きっぷりで理解できるのかは、・・・わからない。
わかりやすく説明って、本当に難しい。。。
そして、書いておきながら思う。自分の理解もまだまだ足りてないな。。。
ちなみに、ところどころに出てくる図は、PlantUMLをVSCodeのPlantUMLプラグインと組み合わせて作っています。
DSLベースの作図ツールはmermaid.jsもよかったけど、PlantUML+VSCodeの組み合わせはリアルタイムに作図結果のプレビューが見れて、とてもいいです。