🔄

gh extension で hub sync の代替となる gh sync 作りました

に公開

gh sync で 'hub sync' と同等の処理ができる仕組みを作ったので紹介します。また、gh extension ってのがめちゃくちゃ手軽で、今後も git や GitHub 関連のいつもやる処理も自動化するみたいなときにかなり訳に立ちそうだったのでこちらも紹介します。

gh-sync

https://github.com/him0/gh-sync

gh extension という仕組みに乗っかっており、gh command が入っていればインストールは簡単

gh extension install him0/gh-sync

使い方

# Basic sync
gh sync

# Sync with verbose output
gh sync --verbose

# Sync with color control
gh sync --color=always
gh sync --color=never

# Combine options
gh sync --verbose --color=never

更新

gh extension upgrade gh-sync

作った背景

ずっと愛用している hub command なのですが、gh command のリリースよりもうメンテされてないままになっています。hub command は2022年頃から開発が鈍化して、2023年には開発が止まっています。それと入れ替わる形でリリースされたのが gh command で 2020年にリリースされています。作者が同じ方で gh に移られたので、hub command の開発は下火になったのが背景のようです。

hub の中でも一番使うというか、これに慣れると hub 無しで生きていけなくなるのが hub syncです。upstream の remote branch を検出して、すべての local branch を upstream 追従するという神コマンドです。とりあえずrepository のディレクトリに入ったら hub sync 打っておけば、最新の状態になる知ってしまうと使わないという選択肢がなくなるコマンドです。

特に開発環境を複数持っていて、GitHub に途中の作業を上げておくことが結構ある自分は、このコマンドなしには生きていけないです。なので、更新が止まっている hub command を使わないという選択肢がない状態でした。

hub の開発止めるのなら gh に sync をつけて欲しいという意見は以前より上がっています。

https://github.com/cli/cli/issues/1722

時代的にデフォルトのブランチ名も master から main 主流が変わり、このあたりもたまにデフォルトブランチの認識を間違えて、master ブランチを検知してしまうご動作もちょいちょい見られるようになってきました。

gh extension

今回 gh extension という仕組みで、gh コマンドにサブコマンドを追加したのでその仕組を紹介します。gh extension createコマンドが用意されているので速攻で作れます。詳しくは公式のドキュメントを見てもらうのがいいともうのですが、触りと golang で書くときのポイントだけ紹介します。

go で作るとき precompiled というオプションを利用します。

$ gh extension create --precompiled=go gh-sync
✓ Created directory gh-sync
✓ Initialized git repository
✓ Made initial commit
✓ Set up extension scaffolding
✓ Downloaded Go dependencies
✓ Built gh-sync binary

gh-sync is ready for development!

Next Steps
- run 'cd gh-sync; gh extension install .; gh sync' to see your new extension in action
- run 'go build && gh sync' to see changes in your code as you develop
- run 'gh repo create' to share your extension with others

For more information on writing extensions:
https://docs.github.com/github-cli/github-cli/creating-github-cli-extensions
$ ls -ls gh-sync
total 18528
18496 -rwxr-xr-x@ 1 him0  staff  9468082  7  5 13:34 gh-sync
    8 -rw-r--r--@ 1 him0  staff      767  7  5 13:34 go.mod
   16 -rw-r--r--@ 1 him0  staff     4521  7  5 13:34 go.sum
    8 -rw-r--r--@ 1 him0  staff      505  7  5 13:34 main.go

gh の extension として認識されるためには、条件は

1.リポジトリ名 が gh-<name> の形式であること(例: gh-sync)
2.1 実行権ががある gh-<name> というファイルが repo のルートに存在する
2.2 リポジトリのリリースにある実行ファイル(バイナリ)がある

2.1 と 2.2 はどちらかを満たせばOKとなります。なので実質条件は2つですね。golang クロスビルドが必要になる特性上 2.2 の方の運用になります。

具体的には

  1. .gitignore にバイナリ (gh-sync) を追加
  2. GitHub Actions で各 OS 向けにクロスビルド
  3. gh-sync バイナリを GitHub Release に添付(例: gh-sync-linux-amd64)
    という手順になります。

バイナリの種類に関しては、gh extension をインストールするときに勝手に認識して適切なものをインストールしてくれます。

バイナリの build は .github/workflows/release.yml を使って、タグをつけたらリリースにバイナリをおいてくれる様にだけしておけば動作しました。具体的な実装はhim0/gh-sync の release.ymlを参照すると良いと思います。

作ってみて

gh extension 知らなかったのですが、便利だなと思いましたし、仕組みが小さいの Claude Code で一発出しができる最高な感じだなと思いました。

要望や、機能追加の提案あれば受け付けるので声かけてください
https://github.com/him0/gh-sync

Discussion