はじめに
今回はGit連携のうちでもGitHub連携に特化した機能を紹介します。Android Studioは標準でGitHubだけサポートしており、これだけ特別扱いしています。
GitHubのサイトを開く
まずは簡単な連携機能から紹介しましょう。機能的にはしょうもない部類に属しますが、意外と便利なのがこの「GitHubのサイトを開く」です。
目立つ場所にないので気付いていない方も多いかも知れませんが「Projectツールウィンドウ」のコンテキストメニューの最下部にひっそりと"Open on GitHub "というコマンドがあります。
図1 "Open on GitHub"コマンド
実行してみるとわかりますが、"Open on GitHub "を実行したときに選択していたフォルダやファイルに相当するGitHubサイトをWebブラウザ上に表示します。
図2 "Open on GitHub"コマンドで開いたGitHubサイトの例
何がどうと言うことはないのですが、気楽にGitHubサイトを開けるので思いのほか重宝しています。
「Projectツールウィンドウ」以外だとエディタのコンテキストメニューにも同じ"Open on GitHub "コマンドがあります。エディタで"Open on GitHub "を実行すると、コマンドを実行した行 をハイライト表示してGitHubを開きます。
図3 エディタ上でも"Open on GitHub"が使える
なお、このときにGitHubサイトを開くWebブラウザは「Preferences / Web Browsers」の「Default Web Browser」の指定に従います(通常は、システムデフォルトのブラウザです) 。特定のWebブラウザで開きたい場合は、ここの「Use system default browser」ではないほうのラジオボタンをONにして、使いたいWebブラウザのパスを指定します。
図4 「 Preferences / Web Browsers」設定画面
Gistにスニペットを登録する
GitHubのおまけ的サービスであるGist に任意のコードスニペットを登録することができます。
先ほどの"Open on GitHub "のスクリーンショットでちらちら見えていましたが、このコマンドの真下にある"Create Gist... "でスニペットを登録します。
「Projectツールウィンドウ」上で、このコマンドを実行した場合は、その時選択していたファイルを丸ごとGistに登録します。エディタ上で何も選択してない状態で実行した場合も同じです。
図5 "Create Gist..."コマンドの実行例
エディタ上で特定の範囲を選択した状態で"Create Gist... "を実行すると、その範囲だけがGistに登録されます。その際、表示されるダイアログは先ほどのものと同じです。
ちなみに「Projectツールウィンドウ」上で複数の ファイルを選択した状態でも"Create Gist... "を実行できます。その場合、先ほどとはちょっと違うダイアログが表示されます。複数ファイルを選択した場合は、強制的に先頭のファイル名がGistの登録名になるようです。
図6 複数のファイルを選択して"Create Gist..."を実行した場合
実際に登録してみるとわかりますが「Create Gist」ダイアログの「Filename」にすでに登録済みの値を設定しても別のGist として登録されます。同名のGistのリビジョンが増えて行くわけではないので注意してください。
そして残念な事に、Gistに登録することはできるのですが、Gistからスニペットを取り出すことはできません。たしかに登録だけでもずいぶん便利なのだけれど、登録したスニペットを利用できて初めて意味があるんじゃないのか?と首を傾げざるを得ません。
「なんでGistに登録したスニペットを利用できないんだ?」と思う気持ちは世界共通のようで、ベースになったIntelliJには次のチケットがあがっています。「 自分もそう思う」という方はぜひとも投票をお願いします。
[コラム]GitHubの設定
Android StudioのGitHubの設定は「Preferences / Version Control / GitHub」で行います。設定項目はシンプルでGitHubへのアクセス設定のみとなっています。
図7 「 Preferences / Version Control / GitHub」設定画面
試せる環境がなかったため推測になりますが、GitHubのホスト名を指定できることからGitHub Enterprise でもこの連携機能が使えると思います。
あと、一度Android StudioでGitHub連携を行ったプロジェクトを元に戻す―GitHub連携を解除する方法は見当たりませんでした。単純にリモートリポジトリを削除すれば良いだけではないようです。それほど需要のある操作ではないと思いますが、一応覚えておいてください。
GitHubのfork元の変更を取り込む
他のプロジェクトをforkしてこそのGitHubですが、forkした後にfork元の変更を取り込むにはどうしたらよいでしょうか?Android Studioには、そのためだけの専用コマンドがあります。メニューバーの「VCS → Git → Rebase my GitHub fork」がそうです。
図8 のようにforkした後で、fork元のプロジェクトが育ってしまったケースを元に説明します。
図8 fork元のプロジェクトの変更を取り込みたい
「自分のGitHubには対象のプロジェクトがfork済みで、かつローカルにそのプロジェクトのクローンが存在している」がスタートラインです。Android Studioの「Changesツールウィンドウ / Logタブ」ではリモートリポジトリが設定されているかまではわからないので、SourceTreeでみたローカルリポジトリの様子を図9 に示します。
図9 SourceTreeでみたローカルリポジトリ(処理前)
※画面左端の「リモート」に注目
Android Studioの「Changesツールウィンドウ / Logタブ」で見ると図10 のとおりです。「 HEAD」位置に注目しておいてください。
図10 「 Changesツールウィンドウ / Logタブ」で見た例
作業に入る前に、fork元のプロジェクトが実際に変化しているのかどうかを確認します。Android Studioにそのような機能はないので、WebブラウザでGitHub上の該当プロジェクトのコミットログを確認します。
図11 fork元のプロジェクトが育っていることを確認
図11 の枠で囲っている部分を、forkした自身のプロジェクトに取り込むため"Rebase my GitHub fork "を実行します。ローカルにクローンしているプロジェクトはmasterブランチのHEADにしておいてください。
"Rebase my GitHub fork "を実行すると、通常ならこれといった問い合わせもなく処理を完了します。ステータスバーにいくつかメッセージが表示されますが、一連の作業が完了すると 図 のような通知がポップアップされるはずです。
図12 "Rebase my GitHub fork"の完了通知
コマンド実行後の「Changesツールウィンドウ / Logタブ」の様子は図13 の通りです。確かにコミットログは成長していますが、それがfork元の変更を取り込んだためであることを知るのは難しいです。
図13 "Rebase my GitHub fork"後の「Changesツールウィンドウ / Logタブ」の様子
SourceTreeでみると一目瞭然です。いつの間にか追加されたupstreamリモートリポジトリの内容が取り込まれていることがわかります。
図14 SourceTreeでみたローカルリポジトリ(処理後)
どちらの方法でコミットログを見ても、本来のリモートリポジトリ(origin)に変更を反映していないのは明らかなので、"Push... "(git push
)を実行して、originリモートリポジトリにも変更を反映して、一連の作業は完了となります。
図15 "git push"後のコミットログ
※念のため補足:push先のリモートリポジトリは"origin"を指定します。
「できるはずだけど、やり方がよくわかんないGitHubのfork元と再同期する」がコマンド一発で出来てしまうというのは思いのほか便利です。"Rebase my GitHub fork "が内部で行っている一連の流れを図16 に示します。
図16 "Rebase my GitHub fork"の仕組み
masterブランチをfork元との同期に用いるので、forkしたプロジェクトを扱う場合はmasterブランチはfork元の同期専用とし、通常の開発などに使わないほうが良いでしょう。
プルリクエストを送る
Android StudioからGitHubへ直接プルリクエストを送ることができます。メニューバーの「VCS → Git → Create Pull Request」から実行します。
自分のリモートリポジトリにプルリクエストを送る
今回の検証作業で気付いたのですが、forkしたリポジトリで無くともプルリクエストを送ることができます。要するにプッシュの代わりに、自分のリモートリポジトリに対してプルリクエストを送るわけです。
たとえば、図17 のように特定のブランチ(例では"developブランチ")の変更をプルリクエストとするために"Create Pull Request "を実行してみます。
図17 developブランチの内容をプルリクエストとして送る
コマンドを実行すると、図18 のようなシンプルなダイアログが表示されます。
図18 「 Create Pull Requeset」ダイアログ
「Target branche」のプルダウンには自身のリモートリポジトリ上にあるブランチが一覧表示されます(とりあえず「master」を指定します) 。その隣の「Show Diff」ボタンを押すとプルリクエストを送る範囲が表示されます。プルリクエストの範囲は、今いるブランチのすべての変更が対象になります。範囲を変更する方法は見当たりませんでした。
図19 「 Show Diff」ボタンでプルリクエストする内容を閲覧できる(クリックすると動きがわかります)
「OK」ボタンを押し、プルリクエストの作成が完了すると、右上に図20 のようなポップアップが表示されます。
図20 プルリクエスト完了を示すポップアップ(クリックすると動きがわかります)
ここのリンクをクリックするとWebブラウザが開き、GitHubのプルリクエスト画面が表示されます。あとはGitHub上でこのプルリクエストを受理するかどうかを決めます。
図21 GitHub上のプルリクエスト画面
ここまでの状況を整理すると図22 のようになります。プルリクエストしたローカルの変更分も一旦、リモートリポジトリにプッシュするので、プルリクエスト先のブランチはローカルのブランチとは別にしたほうが都合が良さそうです。たとえば、今回のようにローカルではdevelopブランチで作業を行い、リモートのmasterブランチにプルリクエストを送るなどです。
図22 "Create Pull Requset"の仕組み
図23 プルリクエスト送信後のコミットログ
GitHub上でプルリクエストを受理すると「その時に用いた作業用ブランチも削除するか?」と聞いてきます。ここで「Delete branch」ボタンを押すと、プルリクエスト用に作成したリモートのdevelopブランチが削除されます。すべてを終えた後のローカルでのコミットログは図24 のとおりです。
図24 GitHub上でのプルリクエストの受理(クリックすると動きがわかります)
自分の持ち物であるリモートリポジトリにプルリクエストを送るというのは何となく奇妙な感じがしますが、やみくもにプッシュするのではなくプルリクエストで一旦考慮する時間を得るというのもまんざら悪くないなと思いました。
fork元のリモートリポジトリにプルリクエストを送る
プルリクエストの本来(?)の用途である「fork元のリポジトリにプルリクエストを送る」方法です。当然、作業しているリポジトリは、何かしらのリポジトリをforkしたものであることが前提になります。
先ほどと同じく、作業用のブランチの変更をプルリクエストします。「 Create Pull Request」ダイアログの「Target branch」からはfork元のブランチが選択できるようになっています。
図25 「 Create Pull Request」ダイアログ
※会社の後輩に快く協力してもらってこの検証を行いました。
このまま「OK」ボタンを押せば、先ほどと同じようにプルリクエストを送ります。今度の送り先は、自分のリモートリポジトリではなく、他の人のリモートリポジトリになります。
その前に「View Diff」ボタンを押して、fork先との差分を確認するとリポジトリの内部的には、ひっそりとfork元をリモートリポジトリとして追加します。とは言え、差分を確認するときに「Can't find remote」ダイアログが出るので、それほどひっそりではありませんが……。
図26 「 Show Diff」のためにリモートリポジトリを追加する(クリックすると動きがわかります)
参照しているリモートリポジトリは同じものなのですが、この"Create Pull Requset "で追加するのと、前述した"Rebase my GitHub fork"で追加するリモートリポジトリ名が異なる事に注意してください。どうみても無駄にしかみえないのですが、Android Studioの機能制約上、 表1 のようになります。
表1 同じfork元でもコマンドによって登録名が異なる
fork元をリモートリポジトリに追加するコマンド リモートリポジトリの登録名
"Create Pull Request "で「Show Diff」した場合 fork元のアカウント名で登録する
"Rebase my GitHub fork "を実行した場合 upstream
で登録する
SourceTreeで確認すると一目瞭然です。ちなみに「Show Diff」を押さずにプルリクエストを作成すると、このリモートリポジトリは追加されません。
図27 「 Show Diff」で追加されたリモートリポジトリ
ものは試しと、Android Studioから日本語でプルリクエストを送ってみたところ無事送信できました。
図28 Android Studioからの日本語送信テスト結果
まとめ
Android StudioのGitHub連携は「ちょっとGitHubびいきが過ぎるかな?」と思う程度に充実しており、それなりに 便利です。fork元の変更取り込みやプルリクエストなどコマンドひとつで実行できますが、GitHub側の仕組みをある程度知っていないと無用な混乱を起こすだけなので、IDEにおまかせ楽ちんというわけではないです。
GitHub連携機能としてはもうひとつ、バグトラッキングシステム(Bug Tracking System:BTS) GitHub Issuesとの連携もありますが、こちらはGitHub固有ではなく一般的なBTS連携に属するので、あとでまとめて説明します。
おまけ
おまけに、Git連携として紹介しきれなかった重箱の角的なトピックを紹介します。
git svn, git flow について一言
Gitはとても多機能で、いろんな機能を提供しています。そのうち、よく耳にする機会が多い git svn
と git flow
について補足しておきます。
git svn
はSubversionのリポジトリをGitリポジトリとして扱うコマンドです。残念ながらAndroid Studioはgit svn
をサポートしていません。git svn
でチェックアウトしたリポジトリはGitリポジトリとして扱うことができますが、プッシュやプルでエラーになります。ただし、それを見越した上で扱う事は可能です(コミットまでAndroid Studioで行い、プッシュ/プルはSourceTreeなど専用クライアントから行う、などです) 。
次にgit flow
です。git flow
は自由度の高いGitのブランチ運用にあるモデル(ブランチモデル)を当てはめるためのコマンドです。こちらもgit svn
同様Android Studioではサポートしていません。ただ、これに関しては痺れを切らせてプラグインを作った猛者がいます。
軽く試してみましたが、まだバグがあるのか思ったようには扱えませんでした。
いずれもベースとなっているIntelliJに要望(チケット)があがっています。関心のある方はチケットに投票してもらえると、実現する可能性が高まります。
SourceTreeと連携する
Android StudioのGitサポートはIDEにしてはがんばっているほうですが、どうしても痒いところに手が届かないところがいくつかあります。そうゆう場合はAndroid Studioのイマイチさに落胆せず、すぱっと専用クライアントに切り替えたほうがストレスも少なく済むでしょう。
Gitの専用クライアントとして最近注目されているSourceTreeですが、より簡単にAndroid Studioから呼び出す方法を紹介します。
Mac版 SourceTreeの場合
まずはMac版についてです。Mac版のSourceTreeのアプリケーションメニューから「コマンドラインツールをインストール」を実行します。これを実行すると stree
いうコマンドが /usr/local/bin
にインストールされます。
図29 コマンドラインツールのインストール
まだ紹介していませんが、Android Studioには「External Tools」と呼ばれる外部ツールを呼び出す機能 があります。それと先ほどインストールした stree
コマンドを使って、Android StudioからSourceTreeを呼び出すというわけです。
外部ツールの設定は「Preferences / External Tools」で行います。設定値は表2 のとお
りです。
図30 「 Preferences / External Tools」設定画面
表2 「 Edit Tool」の設定項目の例
設定項目 設定値
Name SourceTree - stree
Options 「Synchronize files after excution」をチェック
Show in 「Menu menu」をチェック
Program /usr/local/bin/stree
Parameters $ProjectFileDir$
Working directory $ProjectFileDir$
または空欄
登録した外部ツールはメニューバーの「Tools」メニューから実行できます。
図31 メニューバー「Tools」に登録されたSourceTree
外部ツールの登録名を「SourceTree - stree」としたのは"Find Action "からも外部ツールを呼び出すことができるためです(部分一致で検索するので「stree」でも実行できます) 。
図32 "Find Action..."でSourceTreeを実行する例(クリックすると動きがわかります)
Windows版 SourceTreeの場合
つづいてWindows版です。残念な事にWindows版のSourceTreeにはコマンドラインツールが存在しません。
苦肉の策ながら、ClickOnceの設定からSourceTree.exe
本体とその起動オプションを見つけ出し、それを外部ツールに登録してみました。
図33 「 Preferences / External Tools」 -「 Edit Tool」ダイアログ(一部抜粋)
「Tools settings」以外はMac版と同じです。
表3 「 Edit Tool」の「Tools settings」の設定例
設定項目 設定値
Program レジストリの「HKEY_CURRENT_USER\Software\Classes \sourcetree\shell\open\command」の値です。
Parameters -url $ProjectFileDir$
Working directory $ProjectFileDir$
または空欄
実行方法はMacと同じです。残念なことにSoureTreeの起動オプションは「-url
」しか見つけることができず、このオプションは指定したURLをリポジトリとしてクローンしようとします。そのため、初回起動時には「Add Working Copy」にURLをコピペしてブックマークしなおさなければなりません。
図34 Android StudioからSourceTreeを起動した場合(クリックすると動きがわかります)
Mac版と異なりWindows版のSourceTreeはブックマークに登録しないと、作業コピーをブラウズすることができないようです。Mac版と比べると、いささか泥臭いやりかたですが、一応WindowsでもAndroid StudioからSourceTreeを呼び出すことができました。
Android Studio v0.3.4以降について
正確には幻のv0.3.3からなのですが、2013年11月9日にリリースされたv0.3.4にIntelliJ IDEA 13βの機能が取り込まれました。これにより「Changesツールウィンドウ / Logタブ」の内容が若干変更になったので、その事について紹介します。
「Changesツールウィンドウ / Logタブ」ですが、パッと見の変化は乏しいのですが、主にツールバーやコンテキストメニューがシンプルになりました。第25回の図2 と比較するとよくわかります。
図35 v0.3.4以降の「Changesツールウィンドウ / Logタブ」
ツールバーは機能を必要限度に絞り込んだのか、ずいぶんとスッキリしてしまいました(図36 ) 。個人的には「Star / Clear Star」と「Filter Starred( ) 」が無くなってしまったことが(原稿執筆的に)ショックでした。
図36 v0.3.4以降の「Changesツールウィンドウ / Logタブ」のツールバーの機能
ツールバーのうち、折りたたみに関するアイコン群とコミットログ左側のグラフは連動しています。グラフ部分はクリック可能で、クリックするとそのグラフでブランチ/マージなどの分岐が起きてない部分を折り畳みます。ツールバーの「Collapse linear branches」「 Expand all branches」はコミットログすべてに対して折り畳み/展開を実行します。
図37 ツールバーのうち、折りたたみに関するアイコン群
一番右側にある「Show long edges」は「なんのこっちゃ?」と思う機能です。折り畳んでいる/展開しているに関わりなく、長い間変化していないブランチに対してグラフを引くのを省略します(省略時は「↓」「 ↑」マークが付きます) 。「 Show long edges」はその省略表記を止めてすべてのブランチのグラフを引く機能です。
図38 コミットログのグラフの折り畳み/展開について(クリックすると動きがわかります)
※履歴が十分に育っているプロジェクトが無かったので、IDEA13βで確認しています(同じことはAndroid Studioでもできます) 。
意味がわかると、それなりに納得ができる機能ですが、はたしてそこまでAndroid Studioで確認しようと思うかは別の話になるでしょう。筆者あたりはSourceTreeなどの専用クライアントで確認しそうですが……。
それと、些細な話ですがコミットログは無限スクロールするようになりました。つまり、下端までスクロールすると自動的にコミットログを更新します。