SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

サポートエンジニアが解説するGitHub

Pull Requestで日本語が文字化けしたときの対処方法

サポートエンジニアが解説するGitHub 第1回

発生のメカニズム

なぜDiff画面だけ?

 なぜ、ファイルビューでは文字化けしないのにDiff画面では文字化けするのでしょうか。

 ファイルビューでは、CharlockHolmesというオープンソースのライブラリを使ってファイルのエンコーディングを推測し、UTF-8以外のエンコーディングだった場合は内部的にUTF-8に変換することで、GitHubのWeb UIの上で問題なく表示できるようにしています。つまり、ファイルのエンコーディング方式が何であっても、表示上はすべてUTF-8に統一されているということです。

 しかしDiff画面では、この推測がボトルネックになります。Diffとはある時点からある時点へのファイルの変更の差分です。更に、その変更はShift_JISからEUC-JPといったような、エンコーディングの変更を含んでいる可能性もあります。したがって、推測処理はそのコミットに含まれるファイルの2倍(差分の変更前と変更後の分)行う必要があります。さらに、差分データは小さいことが多いため、エンコーディングの推測精度が下がります。間違った推測に基づく変換は、さらなる文字化けを引き起こすでしょう。

 このような状況を踏まえ、GitHubでは、Diff画面に限ってはエンコーディングの推測・変換を行わず、全てのBlobのバイト列をそのままUTF-8として解釈するという方針を採用しました。また、その際Unicodeとして不正な文字が現れた場合は全てという文字に置き換えています。その結果、UTF-8以外のエンコーディングは全て文字化けしますが、Diff画面のレンダリング速度は向上しました。

 したがって、この文字化けは、アプリケーションパフォーマンスとのトレードオフの結果と言えます。しかし、後述するSyntax Highlighted Diffsの登場で、この状況が少し変わりました。

シンタックスハイライト

 GitHubでは2014年12月にSyntax Highlighted Diffsという機能をリリースしました。これはソースコードのシンタックスハイライト(構文ハイライト)をDiff画面でも実現する機能です。ただし、全てのファイルがシンタックスハイライトできるわけではありません。マークダウン形式のファイルなど、プログラムのソースコードではないものはハイライトできません。

 Syntax Highlighted Diffsでは、ハイライトの可否を「そのDiffに含まれるBlobの言語が判定できて、かつ言語のTextMateスコープが適切なものかどうか」という基準で判断しています。

 少し脱線しますが、それぞれもう少し詳しく説明します。まず、プログラミング言語の判定にはGitHubが開発したオープンソースライブラリLinguistが使われています。これはテキストファイルの種類を判定したり、そのテキストファイルがプログラミングのソースコードであれば、使用されている言語を判定してくれるライブラリです。GitHub.comのリポジトリ上部にある言語バーの実装にもこのライブラリが使われています。

Linguistを使用した言語バー
Linguistを使用した言語バー

 また、TextMateというのはオープンソースのmacOS向けテキストエディタです。そして、TextMateのスコープというのは、テキストデータをツリーオブジェクトと見なし、そのツリーの特定の範囲(Scope)ごとに文法(Grammar)を定義することで、一つのファイル内に複数の言語が存在しても適切にシンタックスハイライトや補完が実行できるようにする仕組みです。詳細はIntroduction to scopesという記事で詳しく解説されているので、興味があれば読んでみてください。

 このTextMateのスコープと文法は、現在ではSublime Text、Atom、Visual Studio Codeといった他のテキストエディタでもサポートされていて、モダンなテキストエディタ界隈ではデファクトスタンダードとなっています。GitHubでは、このTextMate互換の文法をベースにしたPrettyLightsというシンタックスハイライトエンジンを開発し、それを使ってBlobが適切なスコープを持っているかどうかを判定しています。なお、PrettyLightsはオープンソースプロジェクトになってはいません。

シンタックスハイライトとエンコーディング変換

 では、このシンタックスハイライトの可否がなぜ文字化けと関係があるのでしょうか。GitHubのDiffやSyntax Highlighted Diffsに関係する部分のコードを読むと、シンタックスハイライトができる場合とできない場合で異なった動作を行うことがわかります。

 プログラミング言語が判定できなかった、TextMateスコープが不明なものだったなどの理由でシンタックスハイライトが行われなかった場合は、Diffの扱いはこれまでと変わりません。ところが、シンタックスハイライトができる場合は、前述したPrettyLightsにデータを渡すため、Blobのエンコーディングの推測とUTF-8への変換を行っています。

 もう一度コミットf074f92を見ると、文字化けしている2つのファイルは、シンタックスハイライトされていないことがわかると思います。

 一方、example-utf8.srcというファイルを見てください。このファイルが文字化けしていないのは、そもそもエンコーディングがUTF-8だからです。しかし、シンタックスハイライトされていないので、言語の判定には失敗していることがわかります。example-utf8.jsと比較してみてください。

example-utf8.src
example-utf8.src

次のページ
文字化けを防ぐには

この記事は参考になりましたか?

サポートエンジニアが解説するGitHub連載記事一覧
この記事の著者

水谷 翔(GitHub, Inc.)(ミズタニ ショウ)

 東京都生まれ。工学部建築学科出身。ウェブデザイナー、インフラエンジニア、AWSのデータセンターテクニシャン等のキャリアを経て2016年6月にGitHub, Inc.に入社。Enterprise Support Engineerとして、GitHubの企業向け製品GitHub Enterpriseを導入してい...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11079 2018/09/20 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー