2022年1月8日

[golang] vscode と golang の import(2022/01/08)

今の私は、Ubuntu 20.04 で vscode 1.63.2 を使っている。
go のバージョンはこちら。

$ go version
go version go1.17.6 linux/amd64

 

Microsoft の go extension をインストールしているのだが、うまく動いているような動いていないような、よくわからないときがある。
プロジェクトの設定によるような、よらないような。。。

つまり、よくわかってなのだ。


formatOnSave

よくわからんやつの代表格。
設定項目は、"editor.formatOnSave" と、各言語向け設定の中にある "editor.formatOnSave" だけだと思っている。

01: {
02:     "[go]": {
03:         ....
04:         "editor.formatOnSave": false,
05:         ....
06:     },
07:     ....
08:     "editor.formatOnSave": false,
09:     ....

関連項目に "go.formatTool" もあると思う。

で、どちらにも false を指定している(おそらく共通設定の formatOnSave は個別の言語設定に項目があるなら使われないと思う)のだが、保存すると import が埋められてしまうので、設定が効いていないか別の項目が影響しているかだと思う。

Formatting
https://code.visualstudio.com/docs/languages/go#_formatting

特にそういう情報は載っていない。

 

settings.json で「 "go" 」と書いて Tabキーで自動補完?させると、こういう項目があった。

01:     "[go]": {
02:         "editor.codeActionsOnSave": {
03:             "source.organizeImports": true
04:         },
05:     },

これを false にすると、ファイル保存時に import が更新されなくなった。
つまりあれは format しているわけではなく import の整理をしているだけなのだ。

 

ではこの状態で vscode のコマンドで Format Document すると import が更新されるかというと、されない。
そう、 format は整形だけで、 import の整理とは別なのだ。
別のコマンドで「Organize imports」というのがあるので、そちらを実行すると importが整理された。

キーバインドはこうなっていた。設定した記憶がないので、vscode のデフォルトだろう。

01: {
02:   "key": "shift+alt+o",
03:   "command": "editor.action.organizeImports",
04:   "when": "editorTextFocus && !editorReadonly && supportedCodeAction =~ /(\\s|^)source\\.organizeImports\\b/"
05: }

Go言語用というわけでもないと思うのだが、どういうしくみなんだろうね?

 

Format Tool で "goimports" を指定しておくと format時に importも整理されていたのだが、最近はLanguage Serverなるものを使うのがデフォルト設定になっていて、その場合は Format Tool の設定は無視されるらしい。
「Use Language Server」を false にすると Format Document 時に importが整理された。

import を自動で更新してくれると便利でよいのだが、勝手にソースファイルが変更されるのが嫌なときもあるのだ。単純に「勝手に変わるのは気持ち悪い」というだけかもしれんが、まあそういうものだ。


あとは、文字色だけ付けるモードがあるとありがたい。
import が足りないとかそういうのはチェックせず、単に予約語などに色を付けるだけのモードだ。保存するたびに CPU負荷が上がるところを見ると、簡易的なコンパイルなり何なりを実行しているのだと思うけど、私の場合はそういうのいらないからさっさと動いてくれ、ということが多いのだ。

 

Microsoft の Extension を外して、 "Go Custom Format" で goimports などを指定すればだいたいよさそうな気がする(Format Document、ではなく extensionのコマンドで format することになるが)。
色を付けるのは vscode の設定だけでよさそう。もしかしたら今まで golang で使った設定が残っているだけかもしれんけど。

そんなに毛嫌いしなくても良いと思うのだが、Save して数秒間チェックしてから保存されたりすると、何もしないでいいから保存を先にしてくれ~といいたくなってしまうのだ。

 

あまり難しく考えず、遅いときだけ Extension を disable にしておく、でもよいのかもしれんし、Language Server を使わなくしただけで軽くなったような気がしなくもない。 gopls がないと起動するときに怒られるが、インストールしておくと使われてしまいそうなので、同じ名前の空のファイルを作って実行権限でも与えておくと良いだろう。そこまで毛嫌いしなくてもよいとは思うが。

[golang]結局「プログラミング言語Go」を買った

前回、買うかどうかくよくよしていたが、買った。紙の方。

プログラミング言語Go - 丸善出版 理工・医学・人文社会科学の専門書出版社
https://www.maruzen-publishing.co.jp/item/b304432.html

ネイティブのバイナリを作るし、もう少し慣れれば私の C言語以外の主要言語に格上げされることだろう。

 

私にとってこの本の良いところは、だいたいのところをカバーしていそうなところ(まだ読み切ってないので)と、プログラミング言語を扱ったことがある人向けというところだ。初学者向けだと、わかりやすく説明しているだけなのか言語仕様なのか判断できないことがあるからだ。あとは読んでいて「そういうのは分かってるから中身だけ書いてくれ」と思ってしまいそうだからというのもある。

電子書籍にするかどうかは少し迷ったところである。
紙媒体にしたのは、私が電子書籍だと読まないからだ。

この本として気をつけることは、go のバージョンが v1.5 になっていることだろう。
新しくなった部分は自分で取り込むしかない。


こうやって情報がまとまっていて助かるところは、調べようともしなかった情報に気付くことだと思う。

たとえば「ルーン(rune)」なんてものは存在すら知らなかった。%c なんだから文字コードだろう、などと決めつけてはいかんということだろう。
C言語だと「文字列」というのは「\0で終わるデータ」くらいのイメージしかないので、なんかこう Unicode とかそういうのはライブラリにお任せするのだが(そもそも私は文字列をあまり扱わないのだけど...)、言語仕様に入ってるなら知っておかないといかんよね。

 

しかし、それは目を通さないと情報に気付かないということでもある。
この本は約400ページくらいあり、絵や図はそこまで多くないし、コードもそこまでないので、つまり情報量がかなり多い本になる。密度が濃いといえばよいか。

なので、読むのにも時間かかるし、負担が結構かかりそうだ。
ああ若いときに読みたかったわ。。。

2021年12月20日

golangの本を買いにいったが止めた

golang をネットで場当たり的に調べるのも良いが、本を買ってじっくり学ぶというのもやりたい。
私はまだ技術書をデジタル書籍ではうまく扱えないので、本屋さんに行ってきた。

紀伊國屋と丸善を回ったのだが、どちらも同じような状況だった。
買わずに家に帰って調べたのだが(買いに行く前にやれってね)、本屋さんにあったような本しかなかった。

 

入門書でも良いのだけど、インストールの仕方とかツールの使い方とかに比重が置かれているタイプではなく、サーバプログラミングに重点を置いているようなものでもなく、言語仕様に重点が置かれている本が買いたかったのだ。

となると、これしか出てこない。

プログラミング言語Go - 丸善出版 理工・医学・人文社会科学の専門書出版社
https://www.maruzen-publishing.co.jp/item/?book_no=295039

本屋さんにもあったのに買い控えたのは、これが2016年出版と5年前だからだ。オリジナルは2015年。
電子書籍版も2021年5月に出ているのだが、内容が更新されたわけではないだろう。
C言語だと多少古くてもなんとかなると思うのだが、Go言語は最近の言語。
6, 7年も前だと変更がいろいろ行われていそうで止めたのだ。

候補になりそうなのはオライリーさんのだけど、これはまだ日本語になってない。

Learning Go [Book]
https://www.oreilly.com/library/view/learning-go/9781492077206/

というわけで、買うのを止めたのだった。


しかし家に帰ってよく考えたのだが、ツールの使い勝手が変わっても言語自体は変わってないのかも・・・?
そこを調べておくべきだろう。

  • v1.1
    • integer division by zero
    • surrogates in Unicode literals
    • method values
    • return requirements
  • v1.2
    • use of nil
    • three-index slices
  • v1.3
    • 無しなのかな?
  • v1.4
    • for-range loops
    • method calls on **T
  • v1.5
    • map literals
  • v1.6
    • 無し
  • v1.7
    • terminating statements
  • v1.8
    • explicit converting
  • v1.9
    • type aliases
    • 浮動小数点演算の丸め関係
  • v1.10
    • 一応無し
  • v1.11
    • 無し
  • v1.12
    • 無し
  • v1.13
    • リテラルのプレフィクス追加(0b, 0o など)
    • ビットシフト量を unsigned に変更
  • v1.14
    • overlapping interfaces proposal
  • v1.15
    • 無し
  • v1.16
    • 無し
  • v1.17
    • conversions from slice to array pointer
    • unsafe.Add()
    • unsafe.Slice()
  • v1.18
    • これを書いている時点では未定
    • 404 は "to, err := human()" なのね

あまり読まずに抜き出したので、間違いがあったら済まぬ。

 

 

オリジナル本の "The Go Programming Lanuguage" は、どうも v1.5 の時代に書かれているようだ(Contents の PDFより)。

v1.6 以降で気になる変更点は、type alias のサポートとか interface関係かなぁ。
しかし標準ライブラリへの変更や追加もあるだろうから、やっぱり悩むな。。。

2021年12月19日

[golang]go.mod の require にリリースバージョンを付けたい

以前、go.mod で特定の commit-id を指定するやり方を調べた。

hiro99ma blog: [golang] go.mod の pseudo-version
https://hiro99ma.blogspot.com/2021/12/golang-gomod-pseudo-version.html

が、よく考えれば普通は pseudo じゃないバージョンを使っているのだ。
そのバージョンの指定方法を調べておくべきだろう。

https://go.dev/doc/modules/gomod-ref#require

require の文法は

require module-path module-version

で、リリースバージョンか pseudoバージョンとのこと。

リリースバージョンってなんじゃ?
git tag でよいのか?

前回の gogo-test4 に v0.1.0 のタグを付けて push。
GitHub のリリースにはしていないが、tags には出てくる。

https://github.com/hirokuma/gogo-test4/tags

で、これを require している gogo-test3 で指定する。

https://github.com/hirokuma/gogo-test3/blob/66a97f39163f91ab9bd945a1c45ff80de37a6d7d/go.mod#L5

go mod tidy してもエラーにならないから、これでよいようだ。

ただ、git tag って push した後でも消したり差し替えたりできると思うので安心しきってはいかんのかもしれんな。

[golang]ライブラリが持つグローバル変数

グローバル変数と呼んでよいのかどうかわからんが、パッケージ内に変数を置けばグローバル変数みたいな扱いができると思う。
小文字だとパッケージ外からはアクセスできないが、ローカル変数かグローバル変数かでいえばグローバル変数だからどこからアクセスしても本体は同じだ。

 

さて、ではこれがライブラリだったらどういう扱いになるのだろうか?
もし1箇所でしか使っていないなら気にしなくてよいと思うが、複数のパッケージで同じライブラリを import していたら、それは別のメモリとして扱われるのか、同じメモリとして扱われるのか。

https://github.com/hirokuma/gogo-test3

https://github.com/hirokuma/gogo-test4

gogo-test3 の中にパッケージ gogo1 と gogo2 があって、それぞれグローバル変数(パッケージ変数、の方が良いのか?)を置いている。
そしてそれぞれが gogo-test4 を import している。

gogo-test4 はグローバル変数がある。

gogo-test3 の main() で、gogo1 の中で gogo1 と gogo-test4 を更新 → gogo2 の中で gogo2 と gogo-test4 を更新 → gogo1 側の gogo-test4 の値を見てみる、ということをやっている。
結果はこうなる。 2つ数値が出力されるうち、前者が package 内のグローバル変数、後者が gogo-test4 のグローバル変数である。

$ go run .
gogo1 10, 10
gogo2 20, 20
gogo1 10, 20

gogo2 で設定した gogo-test4 の値が gogo1 の方でも取得されているので、取りあえずこういうシンプルな書き方であれば import を複数の箇所で行っていても 1つのものだと判定されるようだ。
New 関数を package が持っていることが多いのは、動的に変数を用意しないと知らないところからアクセスされて値が書き換わっていた、なんてことが起きてしまうのを防ぐためだ。
あるいは、どこからアクセスしても同じデータを使いたいなら、あえてそう作ればよいということだ。

2021年12月5日

[golang] go.mod の pseudo-version

hiro99ma blog: [golang] go.mod の pseudo-version の調べ方がわからん
https://hiro99ma.blogspot.com/2021/11/golang-gomod-pseudo-version.html

git log を加工したらよいのではなかろうか、ということでこうなった。

TZ=UTC git log -n1 --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S

 

たとえばここだとこうなる。

$ TZ=UTC git log -n1  --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S
commit 382e4677bbfb (HEAD -> main, tag: v3, origin/main, origin/HEAD)
Author: hirokuma <hiro9ma@gmail.com>
Date:   20211121014212

    v3

最初は時間がJSTになってて、go mod tidyするとタイムスタンプが違うといわれてしまった。
かといってどうやって UTC にするんじゃ?ってなって。TZ 設定したけど --date=format: にしていたので反映されずに悩んでしまった。

metadata - Git: show dates in UTC - Stack Overflow
https://stackoverflow.com/questions/21363187/git-show-dates-in-utc

 

先頭の 1つだけしか出力しないのだが、私の使い方だとそれで十分だ。

が、ちょっと欲が出るよね?
もうちょっと go.mod 風の出力にならんだろうかと。

$ TZ=UTC git log -n1  --abbrev-commit --abbrev=12 --date=format-local:%Y%m%d%H%M%S --format=format:%ad-%h
20211121014212-382e4677bbfb

コマンドラインが長いのだけど、どうせ記憶できる長さじゃないので alias にでも設定しておけばいいや。

2021年11月21日

[golang] go.mod の pseudo-version の調べ方がわからん

わからんのだ。。。

 

golang で go.mod を作って require にて自分の GitHub リポジトリにあるコードを使う場合、 pseudo-version を書くのだろうと思っている。

https://golang.org/ref/mod#pseudo-versions

フォーマットはこんな感じ。

v0.0.0-<YYYYMMDDhhmmss>-<commit-id>

私が書くときはこういう順番でやっている。

  1. GitHub などで使いたい commit-id を調べる
  2. “YYYYMMDDhhmmss”のところは適当な日時にしておく
  3. “commit-id”のところに調べたcommit-idを書く
  4. go mod tidy
  5. commit-id の桁が長すぎると怒られるので、エラーメッセージに出力された文字列に置き換える
  6. go mod tidy
  7. タイムスタンプが違うといわれるので、エラーメッセージに出力された文字列に置き換える

commit-id は先頭から12文字分とってくればよいので、まだなんとかなると思うのだがタイムスタンプが分からんのだ。
コミットした日時をUTC変換すれば良いのだけど、GitHub だと秒数が出てこない。
clone してくればよいのだけど、めんどくさい。clone するくらいだったら↑でやってしまえばいいや、ということで今に至っているのであった。

go mod edit だとうまいことやってくれないかと期待したのだが、-require は少なくとも書いたとおりに go.mod に書くだけだった。
んー、大した作業ではないのだけど、なんかきれいにできないものか。

[golang][grpc]protocの準備

golang で gRPC をやりたい。

ということは、protobuf がいるので、protoc がいる。
準備しよう。


インストール手順があった。

Protocol Buffer Compiler Installation | gRPC
https://grpc.io/docs/protoc-installation/

これを書いている時点での最新版は v3.19.1。

https://github.com/protocolbuffers/protobuf/releases/tag/v3.19.1

私が動かしている Ubuntu にも protoc はインストールされていたのだが、あんまり新しくない。

$ protoc --version
libprotoc 3.6.1

GitHub の方からコンパイル済みの zipファイルをダウンロードして、$HOME/.local に展開する。

$ protoc --version
libprotoc 3.19.1

新しくなった。


golang で使うには protobuf compiler だけでは足りない。
というか、protoc はプラグインで各言語向けのソースを吐き出してくれるので、その準備がいる。

golang の場合は楽だ。

Quick start | Go | gRPC
https://grpc.io/docs/languages/go/quickstart/

今見ると、 protoc-gen-go@v1.26 と protoc-gen-go-grpc@v1.1 になっているが、protoc-gen-go の latestは v1.27.1 だった(protoc-gen-go-gprc の latestはv1.1.0だった。)。
v1.27.1 にした方がよいのかな? メジャーバージョンアップでもないし新しい方がよいかもしれん。困るまで v1.27.1 にしてみよう。
GOPATH は好きに設定すれば良いが、プロジェクトごとに GOPATH を設定しているならどこかにまとめておいた方がよいだろう。

 

Quick Start の順番にやっているので、次は example だ。
今は grpc-go の v1.41.0 を clone するよう書かれているが、最新は v1.42.0 だったのでそちらにした。

まずサーバ側を起動。

$ go run greeter_server/main.go
go: downloading github.com/golang/protobuf v1.4.3
go: downloading google.golang.org/protobuf v1.25.0
go: downloading golang.org/x/net v0.0.0-20200822124328-c89045814202
go: downloading google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98
go: downloading golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
go: downloading golang.org/x/text v0.3.0
2021/11/21 13:21:11 server listening at [::]:50051

別のターミナルからクライアントを起動すると、たぶんサーバ側と通信している。

$ go run greeter_client/main.go
2021/11/21 13:22:03 Greeting: Hello world

こちらはサーバ側の出力。

2021/11/21 13:22:03 Received: world

うん、なんというか、protoc などを自分でやっていないので、gRPC したって気分になれないね。
というわけで、その次の gRPCサービスの更新をやろう。


さて、ファイルの構成はこんな感じ。

image

サーバとクライアントにそれぞれ main.go があって、あとは protoファイルとコンパイルされた pb.go と _grpc.pb.go がある。
ただの pb.go の方は protobuf のシリアライズ/デシリアライズの処理、_grpc.pb.go の方は gRPCのサーバ/クライアントの処理になっているそうだ(basics tutorial)。

あまり深く考えず、proto ファイルに SayHelloAgain()を追加しよう。
そして protoc でコンパイル。
--go_ が pb.go で --go-grpc_ が _grpc.pb.go になる。paths=source_relative は相対パスの場所にファイル生成する。

protoc でコンパイルできたら、それぞれの main.go を変更して同じように実行させると SayHelloAgain が動いていることが確認できるだろう。


ツールとしてはこのくらいあれば golang で gRPC できることがわかった。
あとは・・・知識がいるだけである。

[golang, github]go.modのmoduleを実物と違うのにしてよいのか

go.mod に慣れていないせいかもしれないが(golang自体にも慣れていないが)、非常に難しく感じる。

文句を言っても仕方ない(か、golangのプルリクを出すとか)ので、理解に努めよう。

$ go version
go version go1.17.3 linux/amd64


golang でオリジナルのものを作るときは気にならないかもしれないが、GitHub で fork したり mirror したりして一部を書き換えたいとなると思考が止まってしまう。

 

よくあるのが、git cloneする中でも改造して使いたいのはその一部だけ、というパターンだろう。
例として、fmt.Printf するだけのリポジトリを用意した。

https://github.com/hirokuma/gogo-test1/tree/v1

main.go と gogo/gogo1.go だけだ。

ここの gogoパッケージにある Gogo() だけ使うリポジトリがこちら。

https://github.com/hirokuma/gogo-test2/tree/v1

特に変な動作はしない。

go.mod は自分で記述したわけではなく、 go tidy で勝手に追加されたように思う。

それはよいのだが、gogo-test2 の方を go build . でビルドすると gogo-test2 というバイナリファイルができあがる。
これはなぜかというと、go.mod の module がそういう名前になっているからだ。
もしここで、オリジナルと同じ gogo-test1 という名前にしたくて go.mod の module を github.com/hirokuma/gogo-test1 にすると go build . は失敗する。

$ go build .
main.go:6:2: no required module provides package github.com/hirokuma/gogo-test1/gogo; to add it:
        go get github.com/hirokuma/gogo-test1/gogo

main.go:6 は import "github.com/hirokuma/gogo-test1/gogo" している箇所だ。

ではオリジナルと同じ名前のバイナリファイルを作るのには go build だけで無理なのかというとそうでもない。
あまり理解できていないのだが module path とか module directory という考え方があるようで、うーん、後ろに v2 とか書けばいけるのかな?

https://github.com/hirokuma/gogo-test2/blob/v2/go.mod#L1

いけた。

自分より前に v2 を使っている人がいたら私が v3 にしないといけないかというと、たぶんそういうことではないはずだ。調べるのは無理だろうし。
もし v2 でダメになるのはオリジナルが v2 などにした場合だろう。

 

さて、 gogo-test2 から gogo-test1/gogo にある Gogo() を呼び出していたが、自分で gogo.Gogo() を定義し直したいとしよう。

https://github.com/hirokuma/gogo-test2/blob/v3/gogo/gogo1.go

これを実行すると、gogo-test1 の Gogo() が呼び出される。

$ go run .
gogo-test2!
gogo!

なぜかというと、gogo-test2/main.go で import しているのが gogo-test1/gogo だからだ。
では、go.mod で置き換えてみよう。

https://github.com/hirokuma/gogo-test2/blob/v4/go.mod

うまくいくかと思ったが、これではダメだった。

$ go run .
gogo-test2!
gogo!

main.go の import を変更すればよいと思うのだが、本体の変更をせずに go.mod だけで管理できるようになっていると思うのだよ、私は。

難しいねぇ。続きは明日だ。


明日になった。続けよう。
ここまでを整理しておこう。

gogo-test2/v3 から追加した gogo/gogo1.go を main.go で参照させたいのだが、うまくいっていない。
gogo-test2/v4 で replace を追加したのだが、やっぱり参照してくれない。
もちろん、main.go の import を gogo-test2 に変更すれば参照する。

あれ、もしかしたらそれで問題ないのか?
そもそも gogo を自分で実装したものを使う時点で gogo-test1 とは何の関係もなくなっているのだ。
なので、関係をなくした v5を作った。

https://github.com/hirokuma/gogo-test2/compare/v4...v5

これを gogo-test1 の人が見て、あら私もこっちの gogo を使ってみたいわ、と思ったらこうなる。

https://github.com/hirokuma/gogo-test1/compare/v1...v2

うーん、これでよいような気もする。

 

 

では、gogo-test2 の module を yoshio に変更してみよう。

https://github.com/hirokuma/gogo-test2/compare/v5...v6

go.mod を変更すると main.go の import も変更しないといけなかった。
しかし、これだと git clone しないといけないのだったら gogo-test2.git だとわからないんじゃなかろうか?

gogo-test1/v2 の go.mod を gogo-test2/v6 に変更したらやはりエラーになった。

$ go get
go: github.com/hirokuma/gogo-test2@v0.0.0-20211121012830-b239fb1fd1ae: parsing go.mod:
        module declares its path as: github.com/hirokuma/yoshio
                but was required as: github.com/hirokuma/gogo-test2

こういう場合も replace で対応するようだ。

https://github.com/hirokuma/gogo-test1/compare/v2...v3

なので、module と実物のパスが異なってもなんとかなりそうだ。

2021年11月20日

[git, golang]GitHubのorganizationのprivateリポジトリをgo getする

golang で作業している。
お仕事なのでプライベートリポジトリなのだが、場所が個人ではなくorganizationにある。

さて go getしたいのだが、organization には Personal Access Token (PAT)はない。
どうしたらよかろうか?

$ go version
go version go1.17.3 linux/amd64


検索して出てきたのは2つの方式だった(他にもあると思うけど)。

  • PATでアクセス
  • SSHにする

PAT方式で出てきたのはこちら。

https://zenn.dev/shootacean/articles/go-get-from-github-private-repository

organizationだからPATはないと書いたが、ここでは個人アカウントのPATを使う。
つまり、個人アカウントだろうとorganizationだろうと気にするなということだ。

これでできた。
GOPRIVATEは設定しなくても特にエラーは出なかった。

 

SSH方式で出てきたのはこちら。

https://gist.github.com/magnetikonline/3ceec9ece11375393ab5781d9370ee99

こちらはダメだった。
git clone で https://github.com で始まるリポジトリ名を打ち込むと SSHのパスフレーズを要求されたのでできるかと思ったのだけど、go getの方は「git@github.com: Permission denied (publickey)」としばしば見かけるエラーになった。

表示しているコマンドもcloneしているだけだし、そのまま打ち込んでもやっぱりパスフレーズ要求になったから、stdinを止められてるとかでダメなんだろうか。

~/.netrc で入力を回避するやり方も出ていたので、それと併用するのかもしれんが、試してはいない。

 

というわけで、「GitHubのorganization のプライベートリポジトリを go get するとき、個人アカウントのプライベートリポジトリをPATを使って go getするやり方と同じで取得できた」ということにしておく。

 

GOPRIVATEがいるのは、おそらく go.mod の中にプライベートリポジトリがある場合だと思う。
go get してエラーになるようだったら、GOPRIVATEに github.com/xxx みたいなのを設定すればできた。
全部同じ organizationのプライベートリポジトリだったのだけど、複数の organization にまたがってかつプライベートリポジトリとかだとわからんね。そんなことをするなってことだろうけど。