Macで使えるGitフロントエンド

元々IDEとか開発ツールは専門分野(?)なので、この手のものは以前からいろいろ試しているのですが、個人の感想をまとめておきたいと思います。IDEやエディタに統合されていて利用シーンが限定されるものや、GitHub for Windowsなどのように機能に制限の多いものは省いています。

SourceTree

f:id:takezoe:20170830101400p:plain

  • 信頼と実績のAtlassian製
  • 無料で使用可能(要ユーザ登録)
  • 日本語対応しており、書籍などの情報もある
  • リポジトリごとにウィンドウが開く(Windows版はタブで開くのに…)
  • 対話型リベースが可能
  • 動作がかなり重い、特にブランチが増えると実用に耐えないレベルで重くなる
  • ただし突然死などはしない

Tower2

f:id:takezoe:20170830101412p:plain

  • 有料(買い切り$79)
  • 履歴一覧でブランチの関連を把握するのが難しい気がする
  • 1ウィンドウで複数リポジトリを切り替えて使用
  • 動作はかなり軽い
  • 時々突然死することがある
  • ブランチを切り替える際に未コミットのファイルがあると自動的にスタッシュしてくれるなど細かい部分で気が利いている
  • ターミナルから起動するためのコマンドが用意されている
  • ブランチを複数選択してまとめて削除できる

GitKraken

f:id:takezoe:20170830101434p:plain

  • 非商用利用は無料、商用利用は有料($49/年)
  • 見た目がきれい、ヒストリが見やすい
  • 1ウィンドウで複数リポジトリを切り替えて使用
  • 動作はそれなりに軽い(SourceTree <<<< GitKraken < Tower2という感じ)
  • 初期の頃は不安定で突然死することも多かったが最近は安定してきた
  • 対話型リベースはできないが複数コミットを範囲選択してスカッシュできる
  • GitHub連携機能が便利(フォークしたリポジトリをリモートリポジトリに追加できたり、プルリクエストのブランチを一撃でチェックアウトするなどの機能がある)

まとめ

正直どれも一長一短という感じですが、いまのところ個人的にはGitKrakenが一番使いやすく、開発速度やマーケティングの面でも勢いを感じます。

他にもSmartGitやGitHub for WindowsなどのGUIクライアントや、EclipseIntelliJAtomなどIDEやエディタのGit連携機能を使うという方法もあります。また、GUIではありませんが、Emacsでmagitを使うなどという選択肢もあるのでいろいろ試してみて使いやすいものを選ぶといいんじゃないかと思います。

go-promptでGitのブランチをいい感じにチェックアウトするコマンドを作ってみた

先日Qiitaで以下の記事を見てこれでなにか作れないかなぁと思っていたのですが…

qiita.com

ふと思い立ってGitのブランチをチェックアウトするコマンドを作ってみました。

github.com

ブランチの一覧からチェックアウトしたいブランチをインクリメンタルサーチしてチェックアウトできるというもので、ローカルブランチの場合は普通にチェックアウト、リモートブランチの場合はローカルブランチを作成してチェックアウトしてくれます。

f:id:takezoe:20170828190434p:plain

一応目的のモノは作れたのですが、元々は以下のようなシェルスクリプトを使って、pecoを使ってチェックアウトするブランチを選択できるようにしたものを使っていたのですが、これと比べるとなんだか使いにくい気がする。

function peco-git-checkout() {
  local BRANCH=`git branch -a | peco`
  if [[ -z "$BRANCH" ]]; then
    return
  fi
  if [[ "$BRANCH" =~ remotes/([^/]*)/(.*) ]]; then
    git checkout -b ${BASH_REMATCH[2]} ${BASH_REMATCH[1]}/${BASH_REMATCH[2]}
  else
    git checkout $BRANCH
  fi
}

慣れの問題かもしれませんが…。うーん…。

Scala用のタイプセーフなSQLビルダtranquil 0.0.3をリリースしました

github.com

以前から少しずつ進めていたtranquilですが、APIもそれなりに落ち着いてきたので久しぶりにバージョンアップしてみました。ちなみに以前のものはこんな感じでした。

takezoe.hatenablog.com

テーブル定義は以下のような感じで随分シンプルに定義できるようになりました。

import com.github.takezoe.tranquil._

case class User(userId: String, userName: String, companyId: Option[Int])

class Users extends TableDef[User]("USERS") {
  val userId    = new Column[String](this, "USER_ID"),
  val userName  = new Column[String](this, "USER_NAME"),
  val companyId = new OptionalColumn[Int](this, "COMPANY_ID")

  override def toModel(rs: ResultSet): User =
    User(userId.get(rs), userName.get(rs), companyId.get(rs))
}

object Users {
  def apply() = new SingleTableAction(new Users())
}

case class Company(companyId: Int, companyName: String)

class Companies extends TableDef[Company]("COMPANIES") {
  val companyId   = new Column[Int](this, "COMPANY_ID"),
  val companyName = new Column[String](this, "COMPANY_NAME")

  override def toModel(rs: ResultSet): Company =
    Company(companyId.get(rs), companyName.get(rs))
}

object Companies {
  def apply() = new SingleTableAction(new Companies())
}

マクロで自動生成する手法も試してみたのですが、IntelliJで補完が効かなかったりなど厳しい感じだったので現状ではソースコードの自動生成で対応する感じになるかなと思います。ただ、自動生成するとはいってもシンプルにできるのであればそのほうがよいので、そういう意味ではResultSetからケースクラスを生成するメソッドや、コンパニオンオブジェクトでファクトリメソッドを定義しないといけないのがまだちょっと微妙ですね。

クエリはこんな感じです。

import com.github.takezoe.tranquil._
import com.github.takezoe.tranquil.Dialect.generic

val conn: java.sql.Connection = ...

// SELECT
val users: Seq[(User, Option[Company])] =
  Users()
    .leftJoin(Companies()){ case u ~ c => u.companyId eq c.companyId }
    .filter { case u ~ c => (u.userId eq "takezoe") || (u.userId eq "takezoen") }
    .sortBy { case u ~ c => u.userId asc }
    .list(conn)

テーブルのエイリアスを手動で指定する必要がなくなりました。が、既存のモデルを壊さずにエイリアスを自動生成できるようにしたので実装が割と微妙な感じになってしまいました。やはりDSLではASTを組み立てるだけにして、SQLに変換するフェーズとは分けるようにしたほうが良さそうです(なるべくシンプルな作りにしたかったのですが、こうやって複雑になっていくのか…)。

この他にも以前ブログに書いた時点ではまだサポートしていなかった以下のような機能が実装済みです。

  • 特定のカラムだけSELECTする
  • GROUP BY、HAVING
  • ページング(LIMIT、OFFSET的なやつ)
  • DBごとの違いを吸収するためのDialect

ただ、最初にあまり深く考えずに作り始めてしまったこともあり、無理やり辻褄をあわせるためにvarを使っていたり、ランタイムリフレクションを使っていたりと作り的に結構微妙な感じになってしまいました。また、見た目に違和感のないDSLを作ろうとするとどうしてもimplicit conversionを多用することになってしまい、コードがわかりにくくなってしまいます。

一度作ってみて感覚が掴めたので、もう一度ちゃんと設計して作り直したほうがいいかも…。

sbtとpecoでテンプレートを選択してプロジェクトを作成する

sbtではsbt new playframework/play-scala-seed.g8などのようにしてgiter8テンプレートを指定してプロジェクトを作成することができます。

しかし、プロジェクトを作るたびにテンプレートのリポジトリ名を調べるのも面倒です。そこで、giter8のWikiにまとめられているgiter8テンプレートのリストからpecoでインクリメンタルサーチしてプロジェクトを作成できるようにしてみました。

function peco-sbt-new() {
  local TEMPLATE=`curl https://github.com/foundweekends/giter8/wiki/giter8-templates -s | grep "\.g8<" | sed -e "s/</ /g" -e "s/>/ /g" | awk '{print $3}' | peco | head -n 1`
  if [[ -z "$TEMPLATE" ]]; then
    return
  fi
  sbt new $TEMPLATE
}

上記のような感じのスクリプト.bash_profileに入れておき、peco-sbt-newを実行するとテンプレートを選択してsbt newを実行できます。

f:id:takezoe:20170819163550p:plain

これでgiter8のWikiさえメンテしていれば新しいテンプレートも使えるようになります。

ちょっとしたものですが、テストやユーザサポートなどの用途などの目的でgiter8テンプレートからPlayやScalatraのプロジェクトを作成することがちょくちょくあるので割と便利な感じです。

Tower2をコマンドラインから起動する

Tower2Mac*1GUIなGitフロントエンドです。このブログでも以前紹介しましたが、有償*2なだけあり、軽快な動作が売りで使いやすいGitフロントエンドの1つだと思います。

takezoe.hatenablog.com

takezoe.hatenablog.com

で、最近気づいたのですが、Tower2ではCLIツールが用意されており、コマンドラインからディレクトリを指定して起動したりということもできるようです。CLIツールは設定のIntegrationのタブでインストールできます。

f:id:takezoe:20170817025057p:plain

するとgittowerというコマンドが利用できるようになりますので、Gitリポジトリのルートディレクトリで

$ gittower .

などとするとそのリポジトリをTower2で開くことができます。ちょっとしたことなのですが、ターミナル族には嬉しい機能なのではないでしょうか。

*1:現在はWindows版もリリースされています

*2:$79の買い切りモデル

GitBucket 4.15.0をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.15.0をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.15.0

標準プラグインをバンドル

以下のプラグインがGitBucketのディストリビューションにバンドルされるようになりました。

これらのプラグインは管理画面で有効/無効を切り替えることができます。

f:id:takezoe:20170731123257p:plain

Notificationsプラグイン

イシューやプルリクエストのメール通知が gitbucket-notifications-pluginとしてプラグインに分離されました。機能も強化されており、リポジトリやイシュー/プルリクエスト毎にメールを受け取るかどうかをユーザが選択できるようになっています。

f:id:takezoe:20170731123317p:plain

f:id:takezoe:20170731123327p:plain

プラグインのホイットデプロイに対応

プラグインのインストール/アンインストールを、GitBucketを再起動しなくても行えるようになりました。プラグインをインストールする場合はGITBUCKET_HOME/pluginsディレクトリにプラグインのjarファイルを配置します。アンインストールする場合はjarファイルを削除すればOKです。

さらにGitBucketの起動オプションに--plugin_dirオプションが追加されました。これはプラグイン開発者向けの機能で、GitBucketはこのオプションで指定したディレクトリからもプラグインを読み込むようになります。たとえば以下のようにGitBucketを起動します。

$ java -jar gitbucket.war --plugin_dir=<YOUR_PLUGIN_PROJECT_DIR>/target/scala-2.12

プラグインのプロジェクト側で以下のようにしてsbtを実行します。

$ sbt ~package

するとプラグインのプロジェクト側でソースを変更しただけで自動的にjarファイルが生成され、GitBucketにも変更が反映されます。

Slickを3.2.1にバージョンアップ

Slick(GitBucketが使用しているデータベースアクセスライブラリ)を3.2.0から3.2.1にバージョンアップしました。

このバージョンのSlickは前バージョンであるSlick 3.2.0とバイナリ互換性がないため、現在リリースされている多くのGitBucketプラグインが動作しなくなってしまうものと思われます。GitBucketプラグイン開発者の皆様はGitBucket 4.15.0向けにプラグインの再ビルドをお願いできればと思います。

SSHアクセスでed25519キーをサポート

GitリポジトリへのSSHアクセスでed25519キーもサポートされるようになりました。

編集フォームでのMarkdownプレビュー

これまでイシューやコメントの作成フォームではMarkdownのプレビューが可能でしたが、編集画面ではプレビューを行うことができませんでした。このリリースでは編集フォームでもMarkdownのプレビューが可能になりました。

f:id:takezoe:20170731123345p:plain

今回のバージョンではこの他にも様々な改善やバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

Scala福岡 2017でApache PredictionIOの紹介をしました

7月29日(土)に福岡のヌーラボさんオフィスで開催されたScala福岡2017に参加しました。

scala.connpass.com

セッションではApache PredictionIOの紹介と、PredictionIOやelasticsearch-hadoopなどのOSSScala警察として活動してきた中で見かけたScala的にいけてないコードあるある(とその対処法)についてお話させていただきました。

www.slideshare.net

www.slideshare.net

他の皆さんのセッション(2トラックだったのでもう片方のセッションを聴講できなかったのが残念でした!)も興味深いものが多かったですが、特にはてなさんのPlayのバージョンアップの話が大変心に残りました。Slick様…。また、かなり久々にお会いする方々やお世話になっている方々にもご挨拶できたりなど大変有意義な時間を過ごさせていただきました。(Project Mobster懐かしい!!)

次は9月のScala関西サミットですねー。準備しなくてはー。