Git を始めようとすると、たいてい最初に GitHub のアカウントを作らされます。それで
「Git を使う = コードを外部サービスに置く」という理解ができあがる。
私も長いあいだ、そう思っていました。
remote はただのURLで、SSH越しの隣の机のMacでも、tailnet内のミニPCでも、同じディスクの別フォルダでも構いません。
ローカルLLMや社内データを扱うようになってから、この違いが効いてきました。
GitHub はGitのホスティングサービスの1つであって、Git そのものではありません。 Git は 2005年に生まれ、GitHub は 2008年です。3年間、GitHub なしで回っていました。
「プライベートリポジトリにすれば安全」という考え方もありますが、 非公開であることと、外部に置いていないことは別です。 ローカルLLMを動かす動機が「データを外に出さないこと」なら、コードとプロンプトだけ外に出すのは筋が通りません。
GitHub を否定するものではありません。公開したい、外部の人と協働する、CI を回す—— そういう目的があるなら GitHub は最適です。
ここで扱うのは「手元の2〜3台だけで、外に出さずに回したい」場合の構成です。 仕組みが分かれば、後から GitHub を足すこともできます(remote は複数持てます)。
git remote add origin <ここ> の <ここ> に入るものは、次のどれでも構いません。
①が動くのを見たときに、いちばん腑に落ちました。ネットワークすら要らないからです。 同じMacの中で、フォルダを1つ remote にできます。
# 30秒で確かめる — ネットワーク不要 mkdir -p /tmp/demo/hub && cd /tmp/demo/hub git init --bare skills.git # ← これが remote になる mkdir -p /tmp/demo/work && cd /tmp/demo/work git init && echo hello > a.txt git add . && git commit -m first git remote add origin /tmp/demo/hub/skills.git # ← ただのパス git push -u origin main # ← 通る cd /tmp/demo && git clone hub/skills.git copy ls copy # → a.txt がある
GitHub のアカウントもインターネットも使わずに、push と clone が成立しました。 remote の正体は、それだけのものです。
上で --bare を付けました。付けないと何が起きるか、実際に試すとこう出ます。
remote: error: refusing to update checked out branch: refs/heads/main remote: error: By default, updating the current branch in a non-bare repository remote: is denied, because it will make the index and work tree inconsistent remote: with what you pushed, and will require 'git reset --hard' to match remote: the work tree to HEAD.
理由は素直です。相手がそのブランチを開いて作業している最中に、こちらが履歴を書き換えたら、 相手の手元のファイルと記録が食い違うからです。Git はそれを拒みます。
--bare は作業ツリーを持たないリポジトリです。中身は .git の中身そのもの。
誰も編集していないので、いつ push されても矛盾しません。だから中継役には bare を使います。
Mac が2台あるなら、SSH で片方から scp や rsync すれば、
スキルを持ってくること自体はできます。ではなぜ Git なのか。
| scp / rsync で取りに行く | git remote で繋ぐ | |
|---|---|---|
| 方向 | 片方向(取りに行く側だけ) | 双方向。どちらからでも push できる |
| 両方で直したら | 後から上書きした方が勝つ | 分岐として残り、3-way merge で合流 |
| 誰が何をしたか | 残らない | コミット単位で残る |
| なぜそうしたか | 残らない | コミットメッセージに書ける |
| 相手が寝ている時 | 取れない | 手元の複製で作業を続けられる |
| 戻したいとき | 元がもう無い | 任意の時点に戻せる |
決定的なのは2行目だと思います。 「別のデバイスでもスキルを進化させたい」という時点で、両方が書き手になるということです。
コピーは、コピー先で改良しても本家に戻す道がありません。 戻すには手で差分を見て貼り直すことになり、それを何度かやると、どちらが正なのか誰にも分からなくなります。 これが「二度作る」の始まりです。
SSH でコピーしてくる関係は、片方が親でもう片方が子です。子で育てたものは親に還りません。
git remote で繋ぐと、両方が対等な書き手になります。 どちらで作ったスキルも、もう一方に流れていく。 2台目は「取りに行く先」ではなく「一緒に育てる場所」になります。
2台なら、お互いを remote に登録するだけで足りるようです。ただしどちらも作業ツリーを持っているので、 push を受けるための bare をそれぞれに1つ用意することになります。少し面倒です。
3台目が出てきたところで、私はハブ型に切り替えました。常時起動している1台(ミニPCでもNASでも構いません)に bare を置き、全員がそこを見る。組み合わせが増えても、繋ぎ先は常に1箇所です。
Git のサーバに必要なのはSSHで入れることと、bareリポジトリがあることだけです。 専用のサービスをインストールする必要はありません。
普段使っていない古いMacでも、常時起動のミニPCでも、ssh で入れるなら今日からハブになれます。
ハブ側とクライアント側で叩くコマンドを組み立てます。Tailscale を使うなら、ホスト名の欄に
100.x.y.z か MagicDNS 名を入れてください。それだけで外出先からも同じ手順が通ります。
受け取る側にすでに同じフォルダがある場合、clone は空のディレクトリにしか展開できません。 生成したコマンドでは、いったん別名で clone してから中身を移す形にしてあります。
移す前に、元のフォルダを必ず退避してください。片側にしかない設定が消えると、 それこそ「片寄り」の最悪の形になります。
SSH で繋ぐと決めた瞬間、相手のIPアドレスをどう指すかという問題が出ます。
自宅では 192.168.1.x、カフェからは繋がらない、実家では別の番号。
remote のURLを毎回書き換えることになります。
Tailscale のような tailnet を張ると、各デバイスに場所によらない固定のアドレスが与えられます。
そしてもう一つ大きいのが、通信が tailnet の中で閉じることです。 コードもプロンプトも、インターネット上のどのサービスにも渡りません。
ローカルでモデルを動かす動機は、たいてい「データを外に出さないこと」です。 推論を手元でやっているのに、それを呼び出すコード・プロンプト・評価用データだけ外部に置くのは、 説明としても整合しません。
tailnet 内の bare リポジトリなら、推論も、コードも、履歴も、すべて自分の管理下に収まります。 社内で説明する時にも、この線引きは通しやすいはずです。
Tailscale の認証の考え方そのものは 通れたこと自体が認証である — Tailscale の VPN と SSH に書いてあります。
.claude/ を1本私は全部を一度に管理下に置こうとして、一度やめました。いちばん効くもの1本からのほうが続いています。
~/.claude/skills/ — これが本命です。片側にしかないスキル問題が、これだけで消えますCLAUDE.md / AGENTS.md — 前提や約束事。端末で挙動が違う原因の多くはここ.gitignore で外し、
各端末に手で置きます。一度コミットすると履歴から消すのは面倒ですAPIキー・トークン・パスワード・顧客データ・未公開の出願情報。 外部に出していなくても、履歴に残ると端末が1台盗まれた時に全部漏れます。
.gitignore に .env や *_token* を先に書いてから git init してください。
順序が逆だと、最初のコミットに入ります。
ここまでは手順の話でした。なぜ remote がただのURLでよいのか、なぜ両方で直しても合流できるのかは、 Git の内部構造から出てきます。
この3つは、三台で、同じものを二度作る — Gitの内部構造を8層で読む で Layer 4・5・7 として扱っています。手を動かしてから読むと、腑に落ちる速度が違います。
手順ではなく効き方の側は 分かっていないことが、分からない に書きました。git・サイドチャット・書いて公開するの三つが、それぞれ違うものを頭の外に出しています。
この構成で回してはいますが、試せていないことが残っています。
ハブが落ちたときの復旧。各端末が完全な複製を持つから大丈夫なはず、と理解していますが、
実際に壊して戻す訓練をしていません。「はず」で止まっています。
3台以上でのブランチの分け方。いまは端末ごとに分けていますが、これが良いのかは分かっていません。
SSH鍵の配り方。台数が増えたときの管理を、まだ手でやっています。
書いた手順は私の手元で動いているというだけで、これが定石なのかは判断できていません。 もっと良いやり方をご存じでしたら教えてください。
① 上の「30秒で確かめる」を実際に叩く。ネットワークなしで push が通ることを自分の目で見る。
② 生成器で自分の環境のコマンドを作り、~/.claude/skills/ を1本繋ぐ。
③ 2台目から1行直して push してみる。ここで初めて「両方が書き手になる」感触が分かります。