Android Studio最速入門~効率的にコーディングするための使い方

第27回バージョン管理 ─GitHub連携とおまけ

はじめに

今回はGit連携のうちでもGitHub連携に特化した機能を紹介します。Android Studioは標準でGitHubだけサポートしており、これだけ特別扱いしています。

GitHubのサイトを開く

まずは簡単な連携機能から紹介しましょう。機能的にはしょうもない部類に属しますが、意外と便利なのがこの「GitHubのサイトを開く」です。

目立つ場所にないので気付いていない方も多いかも知れませんが「Projectツールウィンドウ」のコンテキストメニューの最下部にひっそりと"Open on GitHub"というコマンドがあります。

図1 "Open on GitHub"コマンド
図1 

実行してみるとわかりますが、"Open on GitHub"を実行したときに選択していたフォルダやファイルに相当するGitHubサイトをWebブラウザ上に表示します。

図2 "Open on GitHub"コマンドで開いたGitHubサイトの例
図2 

何がどうと言うことはないのですが、気楽にGitHubサイトを開けるので思いのほか重宝しています。

「Projectツールウィンドウ」以外だとエディタのコンテキストメニューにも同じ"Open on GitHub"コマンドがあります。エディタで"Open on GitHub"を実行すると、コマンドを実行した行をハイライト表示してGitHubを開きます。

図3 エディタ上でも"Open on GitHub"が使える
図3 エディタ上でも

なお、このときにGitHubサイトを開くWebブラウザは「Preferences / Web Browsers」「Default Web Browser」の指定に従います(通常は、システムデフォルトのブラウザです⁠⁠。特定のWebブラウザで開きたい場合は、ここの「Use system default browser」ではないほうのラジオボタンをONにして、使いたいWebブラウザのパスを指定します。

図4 ⁠Preferences / Web Browsers」設定画面
図4 「Preferences / Web Browsers」設定画面

Gistにスニペットを登録する

GitHubのおまけ的サービスであるGistに任意のコードスニペットを登録することができます。

先ほどの"Open on GitHub"のスクリーンショットでちらちら見えていましたが、このコマンドの真下にある"Create Gist..."でスニペットを登録します。

「Projectツールウィンドウ」上で、このコマンドを実行した場合は、その時選択していたファイルを丸ごとGistに登録します。エディタ上で何も選択してない状態で実行した場合も同じです。

図5 "Create Gist..."コマンドの実行例
図5 

エディタ上で特定の範囲を選択した状態で"Create Gist..."を実行すると、その範囲だけがGistに登録されます。その際、表示されるダイアログは先ほどのものと同じです。

ちなみに「Projectツールウィンドウ」上で複数のファイルを選択した状態でも"Create Gist..."を実行できます。その場合、先ほどとはちょっと違うダイアログが表示されます。複数ファイルを選択した場合は、強制的に先頭のファイル名がGistの登録名になるようです。

図6 複数のファイルを選択して"Create Gist..."を実行した場合
図6 複数のファイルを選択して

実際に登録してみるとわかりますが「Create Gist」ダイアログの「Filename」にすでに登録済みの値を設定しても別のGistとして登録されます。同名のGistのリビジョンが増えて行くわけではないので注意してください。

そして残念な事に、Gistに登録することはできるのですが、Gistからスニペットを取り出すことはできません。たしかに登録だけでもずいぶん便利なのだけれど、登録したスニペットを利用できて初めて意味があるんじゃないのか?と首を傾げざるを得ません。

「なんでGistに登録したスニペットを利用できないんだ?」と思う気持ちは世界共通のようで、ベースになったIntelliJには次のチケットがあがっています。⁠自分もそう思う」という方はぜひとも投票をお願いします。

GitHubのfork元の変更を取り込む

他のプロジェクトをforkしてこそのGitHubですが、forkした後にfork元の変更を取り込むにはどうしたらよいでしょうか?Android Studioには、そのためだけの専用コマンドがあります。メニューバーの「VCS → Git → Rebase my GitHub fork」がそうです。

図8のようにforkした後で、fork元のプロジェクトが育ってしまったケースを元に説明します。

図8 fork元のプロジェクトの変更を取り込みたい
図8 fork元のプロジェクトの変更を取り込みたい

「自分のGitHubには対象のプロジェクトがfork済みで、かつローカルにそのプロジェクトのクローンが存在している」がスタートラインです。Android Studioの「Changesツールウィンドウ / Logタブ」ではリモートリポジトリが設定されているかまではわからないので、SourceTreeでみたローカルリポジトリの様子を図9に示します。

図9 SourceTreeでみたローカルリポジトリ(処理前)
図9 SourceTreeでみたローカルリポジトリ(処理前)
※画面左端の「リモート」に注目

Android Studioの「Changesツールウィンドウ / Logタブ」で見ると図10のとおりです。⁠HEAD」位置に注目しておいてください。

図10 ⁠Changesツールウィンドウ / Logタブ」で見た例
図10 「Changesツールウィンドウ / Logタブ」で見た例

作業に入る前に、fork元のプロジェクトが実際に変化しているのかどうかを確認します。Android Studioにそのような機能はないので、WebブラウザでGitHub上の該当プロジェクトのコミットログを確認します。

図11 fork元のプロジェクトが育っていることを確認
図11 fork元のプロジェクトが育っていることを確認

図11の枠で囲っている部分を、forkした自身のプロジェクトに取り込むため"Rebase my GitHub fork"を実行します。ローカルにクローンしているプロジェクトはmasterブランチのHEADにしておいてください。

"Rebase my GitHub fork"を実行すると、通常ならこれといった問い合わせもなく処理を完了します。ステータスバーにいくつかメッセージが表示されますが、一連の作業が完了すると のような通知がポップアップされるはずです。

図12 "Rebase my GitHub fork"の完了通知
図12 

コマンド実行後の「Changesツールウィンドウ / Logタブ」の様子は図13の通りです。確かにコミットログは成長していますが、それがfork元の変更を取り込んだためであることを知るのは難しいです。

図13 "Rebase my GitHub fork"後の「Changesツールウィンドウ / Logタブ」の様子
「Changesツールウィンドウ / Logタブ」の様子">図13 「Changesツールウィンドウ / Logタブ」の様子" title="図13 "Rebase my GitHub fork"後の「Changesツールウィンドウ / Logタブ」の様子" />

SourceTreeでみると一目瞭然です。いつの間にか追加されたupstreamリモートリポジトリの内容が取り込まれていることがわかります。

図14 SourceTreeでみたローカルリポジトリ(処理後)
図14 SourceTreeでみたローカルリポジトリ(処理後)

どちらの方法でコミットログを見ても、本来のリモートリポジトリ(origin)に変更を反映していないのは明らかなので、"Push..."git pushを実行して、originリモートリポジトリにも変更を反映して、一連の作業は完了となります。

図15 "git push"後のコミットログ
図15 
※念のため補足:push先のリモートリポジトリは"origin"を指定します。

「できるはずだけど、やり方がよくわかんないGitHubのfork元と再同期する」がコマンド一発で出来てしまうというのは思いのほか便利です。"Rebase my GitHub fork"が内部で行っている一連の流れを図16に示します。

図16 "Rebase my GitHub fork"の仕組み
図16 

masterブランチをfork元との同期に用いるので、forkしたプロジェクトを扱う場合はmasterブランチはfork元の同期専用とし、通常の開発などに使わないほうが良いでしょう。

プルリクエストを送る

Android StudioからGitHubへ直接プルリクエストを送ることができます。メニューバーの「VCS → Git → Create Pull Request」から実行します。

自分のリモートリポジトリにプルリクエストを送る

今回の検証作業で気付いたのですが、forkしたリポジトリで無くともプルリクエストを送ることができます。要するにプッシュの代わりに、自分のリモートリポジトリに対してプルリクエストを送るわけです。

たとえば、図17のように特定のブランチ(例では"developブランチ")の変更をプルリクエストとするために"Create Pull Request"を実行してみます。

図17 developブランチの内容をプルリクエストとして送る
図17 developブランチの内容をプルリクエストとして送る

コマンドを実行すると、図18のようなシンプルなダイアログが表示されます。

図18 ⁠Create Pull Requeset」ダイアログ
図18 「Create Pull Requeset」ダイアログ

「Target branche」のプルダウンには自身のリモートリポジトリ上にあるブランチが一覧表示されます(とりあえず「master」を指定します⁠⁠。その隣の「Show Diff」ボタンを押すとプルリクエストを送る範囲が表示されます。プルリクエストの範囲は、今いるブランチのすべての変更が対象になります。範囲を変更する方法は見当たりませんでした。

図19 ⁠Show Diff」ボタンでプルリクエストする内容を閲覧できる(クリックすると動きがわかります)
「⁠Show Diff」ボタンでプルリクエストする内容を閲覧できる` &title=`図19 ⁠Show Diff」ボタンでプルリクエストする内容を閲覧できる` &width=`400` />

「OK」ボタンを押し、プルリクエストの作成が完了すると、右上に図20のようなポップアップが表示されます。

図20 プルリクエスト完了を示すポップアップ(クリックすると動きがわかります)

ここのリンクをクリックするとWebブラウザが開き、GitHubのプルリクエスト画面が表示されます。あとはGitHub上でこのプルリクエストを受理するかどうかを決めます。

図21 GitHub上のプルリクエスト画面
図21 GitHub上のプルリクエスト画面

ここまでの状況を整理すると図22のようになります。プルリクエストしたローカルの変更分も一旦、リモートリポジトリにプッシュするので、プルリクエスト先のブランチはローカルのブランチとは別にしたほうが都合が良さそうです。たとえば、今回のようにローカルではdevelopブランチで作業を行い、リモートのmasterブランチにプルリクエストを送るなどです。

図22 "Create Pull Requset"の仕組み
図22 
図23 プルリクエスト送信後のコミットログ
図23 プルリクエスト送信後のコミットログ

GitHub上でプルリクエストを受理すると「その時に用いた作業用ブランチも削除するか?」と聞いてきます。ここで「Delete branch」ボタンを押すと、プルリクエスト用に作成したリモートのdevelopブランチが削除されます。すべてを終えた後のローカルでのコミットログは図24のとおりです。

図24 GitHub上でのプルリクエストの受理(クリックすると動きがわかります)

自分の持ち物であるリモートリポジトリにプルリクエストを送るというのは何となく奇妙な感じがしますが、やみくもにプッシュするのではなくプルリクエストで一旦考慮する時間を得るというのもまんざら悪くないなと思いました。

fork元のリモートリポジトリにプルリクエストを送る

プルリクエストの本来(?)の用途である「fork元のリポジトリにプルリクエストを送る」方法です。当然、作業しているリポジトリは、何かしらのリポジトリをforkしたものであることが前提になります。

先ほどと同じく、作業用のブランチの変更をプルリクエストします。⁠Create Pull Request」ダイアログの「Target branch」からはfork元のブランチが選択できるようになっています。

図25 ⁠Create Pull Request」ダイアログ
図25 「Create Pull Request」ダイアログ
※会社の後輩に快く協力してもらってこの検証を行いました。

このまま「OK」ボタンを押せば、先ほどと同じようにプルリクエストを送ります。今度の送り先は、自分のリモートリポジトリではなく、他の人のリモートリポジトリになります。

その前に「View Diff」ボタンを押して、fork先との差分を確認するとリポジトリの内部的には、ひっそりとfork元をリモートリポジトリとして追加します。とは言え、差分を確認するときに「Can't find remote」ダイアログが出るので、それほどひっそりではありませんが……。

図26 ⁠Show Diff」のためにリモートリポジトリを追加する(クリックすると動きがわかります)
「⁠Show Diff」のためにリモートリポジトリを追加する` &title=`図26 ⁠Show Diff」のためにリモートリポジトリを追加する` &width=`348` />

参照しているリモートリポジトリは同じものなのですが、この"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」で追加されたリモートリポジトリ
図27 「Show Diff」で追加されたリモートリポジトリ

ものは試しと、Android Studioから日本語でプルリクエストを送ってみたところ無事送信できました。

図28 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 svngit 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 コマンドラインツールのインストール
図29 コマンドラインツールのインストール

まだ紹介していませんが、Android Studioには「External Tools」と呼ばれる外部ツールを呼び出す機能があります。それと先ほどインストールした stree コマンドを使って、Android StudioからSourceTreeを呼び出すというわけです。

外部ツールの設定は「Preferences / External Tools」で行います。設定値は表2のとお りです。

図30 ⁠Preferences / External Tools」設定画面
図30 「Preferences / External Tools」設定画面
表2 ⁠Edit Tool」の設定項目の例
設定項目設定値
NameSourceTree - stree
Options「Synchronize files after excution」をチェック
Show in「Menu menu」をチェック
Program/usr/local/bin/stree
Parameters$ProjectFileDir$
Working directory$ProjectFileDir$ または空欄

登録した外部ツールはメニューバーの「Tools」メニューから実行できます。

図31 メニューバー「Tools」に登録されたSourceTree
図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」ダイアログ(一部抜粋)
図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タブ」
図35 v0.3.4以降の「Changesツールウィンドウ / Logタブ」

ツールバーは機能を必要限度に絞り込んだのか、ずいぶんとスッキリしてしまいました図36⁠。個人的には「Star / Clear Star」「Filter Starred⁠」が無くなってしまったことが(原稿執筆的に)ショックでした。

図36 v0.3.4以降の「Changesツールウィンドウ / Logタブ」のツールバーの機能
図36 v0.3.4以降の「Changesツールウィンドウ / Logタブ」のツールバーの機能

ツールバーのうち、折りたたみに関するアイコン群とコミットログ左側のグラフは連動しています。グラフ部分はクリック可能で、クリックするとそのグラフでブランチ/マージなどの分岐が起きてない部分を折り畳みます。ツールバーの「Collapse linear branches」⁠Expand all branches」はコミットログすべてに対して折り畳み/展開を実行します。

図37 ツールバーのうち、折りたたみに関するアイコン群
図37 ツールバーのうち、折りたたみに関するアイコン群

一番右側にある「Show long edges」「なんのこっちゃ?」と思う機能です。折り畳んでいる/展開しているに関わりなく、長い間変化していないブランチに対してグラフを引くのを省略します(省略時は「↓」⁠↑」マークが付きます⁠⁠。⁠Show long edges」はその省略表記を止めてすべてのブランチのグラフを引く機能です。

図38 コミットログのグラフの折り畳み/展開について(クリックすると動きがわかります)
展開について` &title=`図38 コミットログのグラフの折り畳み/展開について` &width=`368` />
※履歴が十分に育っているプロジェクトが無かったので、IDEA13βで確認しています(同じことはAndroid Studioでもできます⁠⁠。

意味がわかると、それなりに納得ができる機能ですが、はたしてそこまでAndroid Studioで確認しようと思うかは別の話になるでしょう。筆者あたりはSourceTreeなどの専用クライアントで確認しそうですが……。

それと、些細な話ですがコミットログは無限スクロールするようになりました。つまり、下端までスクロールすると自動的にコミットログを更新します。

おすすめ記事

記事・ニュース一覧