フェッチ機能を活用してプルリクエストに習熟しよう!

最近では、プロジェクトの修正もフォークの作成同様、簡単になりました。フォークを作成する際に作業するプロジェクトの完全な遠隔コピーをあっという間に作れるように、変更したいファイルを選択し、編集するを押して修正をコミットする事で、プロジェクト修正が行えます。

仮に、自分がプルリクエスト (以下、PR と表記) の受け取り側である場合はどうなるのでしょうか?優れた Web UI があれば助かりますし、多くの場合はそれで済みます。ボタン操作 1 つで承認マージ、どちらも完了します。

pr-approval

しかし、常にそうはいきません!プルリクエスト (PR) に含まれている変更点をローカルでダウンロードして、テストをいくつか実行し、起きた内容を把握するために自身の IDE における見え方を確認しなくてはならない事もよくあります。

同僚あるいはコントリビューターのプルリクエストをダウンロードする際のステップ、即ち fetchcheckout は、概念的にはシンプルなものの、いくつかの重要な詳細やコツを把握しておくと更に簡単なものになります。

コマンドラインからプルリクエストを簡単に扱う際に git が可能にする、コマンドライン設備を私が分かりやすく説明してみましょう。

始める前に: ブランチ名とステータスでシェルプロンプトの質を高めましょう

私がいつも驚かされるのは、自分が使用している git ブランチ、あるいは自身の作業ディレクトリ内の改変済み/未コミットファイルの有無を表示しないデフォルトのコマンドプロンプトを使用している人たちの多さです。「あ、自分の事だ」と思った方には、私が驚きの方法をお伝えしますのでご安心下さい!

まずは、素晴らしき liquid prompt 等をインストールして下さい。これは、自身の git 作業ディレクトリのステータスに関する優れた注釈を提供してくれます(また、他のあらゆる VCS にも対応してくれます):

liquid-prompt-1

(上のスクリーンショットでは、私が newbranch というブランチを使用し、作業ディレクトリ内で追跡しているファイルに 5 行を追加し、また削除した行数は 0) である事を、私のプロンプトが通知しているのが分かります。

皆が同じリポジトリ上で作業

あなたが自身のチームと同じリポジトリ上で作業している場合、プルリクエストの確認プロセスは非常に単純です: 単に、プルリクエストが作成されたブランチから、プランチの fetchcheckout を行います:

  • 共有リポジトリ上でパブリッシュされた全てのブランチを取得する:
    1
    git fetch origin
    
    
  • 自分の興味のあるリモートブランチを追跡するローカルブランチを作成する:
    1
    git checkout -b PRJ-1234 origin/PRJ-1234
    
    
  • これで、diffmerge、テストを存分に行えます:
    1
    2
    3
    git diff master

    ./run-tests.sh

    
    
  • 納得したら、Web UI に戻り、フィードバックを提供するか、あるいはすぐに変更を承認します。

自らのフォークで作業するコントリビューターの場合

一部のコントリビューターが別個のフォーク内で作業する場合、プロセスが若干変わります。この場合、コントリビューターが機能などをコミットしたリモートブランチを fetch できます:

  • まず、コントリビューターのリモートブランチを追加します:
    1
    git remote add jsmith http://bitbucket.org/jsmith/coolproject.git
    
    
  • 最初に、自身のメインリポジトリである origin から最新のアップデートを全て回収します:
    1
    2
    3
    git checkout master
    git fetch origin
    git merge master
    
    
  • コントリビューターのフォーク上でパブリッシュされた全てのブランチを取得します:
    1
    git fetch jsmith
    
    
  • 自分の興味のあるリモートブランチを追跡する、ローカルブランチを作成する:
    1
    git checkout -b jsmith-PRJ-1234 jsmith/PRJ-1234
    
    
  • これで、diffmerge、テストを存分に行えます:
    1
    2
    3
    git diff master

    ./run-tests.sh

    
    

プルリクエストのリファレンスを使用して作業を減らす

上記は有効な方法ではあるものの、いくつかの点においては事態を悪化させてしまいます:

  • 多数のコラボレーターがいて、それぞれが自身のフォークを使用している場合は?全員のフォークを追加して、個別に処理する事は非現実的です。
  • 一部のフォークにはアクセスすら出来ず、ソースブランチをチェックアウトできない場合は?

上記の問題に対する解決策は、一部の git サーバーが提供しているプルリクエストリファレンスを使用する事です。これから紹介する手順は、一部の git サーバーによってサポートされており、どれを使用するかによって若干の違いが存在します。以下では、Stash と Github において、全てのプルリクエストを fetch する方法を扱います。

Refspecs を恐れるな

最初の必須条件は、Refspecs に慣れる事です。Refspecs はとても快適であり、不安に思う必要はありません。これらは、リモートブランチからローカルリファレンスへのシンプルなマッピング、即ち git に対して「このリモートブランチ (あるいは一組のリモートブランチ) は、この名前空間において、これらの名前に対しローカルにマッピングされなくてはならない」と率直に伝える方法です。

例えば、次のコマンドの場合:

1
git fetch +refs/heads/master:refs/remotes/origin/master

origin 上のリモートブランチ master を、ローカルな origin/master にマッピングするため、次のように入力できるようになります:

1
git checkout origin/master

そのリモートブランチを引き続き参照していて下さい。定義におけるプラスサイン (+) は、たとえ fast-forward でなくても git にリファレンスをアップデートして欲しいと示すものです。

これを使用して全てのプルリクエストをダウンロードする方法は、遠隔リポジトリがどのようにして PR の HEAD を格納するかをマッピングし、簡単に参照できるようローカルな名前空間にこれらをマッピングするものです。

origin (あるいは upstream) 遠隔が定義済となっているとすれば、次の行動を取ります。

注: 何名かの Stash デベロッパーによって正しく指摘されたように、以下に私が表示するリファレンスは undocumented および private と見なされ、いつでも変わる可能性があります。

全てのプルリクエストをダウンロードする: Stash

  • リポジトリをフォークする。
  • フォークをローカルにクローンする:
    1
    git clone git@stash.atlassian.com:durdn/tis.git
    
    
  • upstream オリジナルリポジトリをupstreamとして追加。
    1
    git remote add upstream git@stash.atlassian.com:tpettersen/tis.git
    
    
  • 'upstream’ から最新の HEAD を取得する。
    1
    git fetch upstream
    
    
  • リモート プルリクエストの HEAD をローカルの pr 名前空間にマッピングする、refspec を追加します。これは、config コマンドで行います:
    1
    git config –add remote.origin.fetch ‘+refs/pull-requests//from:refs/remotes/origin/pr/’
    
    
  • .git/config を確認すると、fetch エントリーが以下のようになります:
    1
    2
    3
    4
    [remote “upstream”]
    url = git@stash.atlassian.com:docker/libswarm.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
    fetch = +refs/pull-requests/*/from:refs/remotes/upstream/pr/*
    
    
  • これで、全てのプルリクエストブランチを簡単に fetch できます:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ git fetch upstream

    remote: Counting objects: 417, done.
    remote: Compressing objects: 100% (274/274), done.
    remote: Total 417 (delta 226), reused 277 (delta 128)
    Receiving objects: 100% (417/417), 105.28 KiB | 0 bytes/s, done.
    Resolving deltas: 100% (226/226), done.

    From stash.atlassian.com:docker/libswarm
    * [new ref]         refs/pull-requests/10/from-> upstream/pr/10
    […]
    * [new ref]         refs/pull-requests/100/from -> upstream/pr/100
    * [new ref]         refs/pull-requests/101/from -> upstream/pr/101
    […]
    * [new ref]         refs/pull-requests/109/from -> upstream/pr/109
    * [new ref]         refs/pull-requests/110/from -> upstream/pr/110
    […]

    
    
  • 特定のプルリクエストに切り替えるには、以下のように簡単に行えます:
    1
    git checkout pr/102
    
    

全てのプルリクエストをダウンロードする: Github

フォークあるいはアップストリームが Github 上にある場合、上述と全く同じ仕組みが働きますが config コマンドが以下に変わります:

1
    git config –add remote.origin.fetch ‘+refs/pull//head:refs/remotes/origin/pr/’

.git/config 内の remote セクションが変更され、追加の fetch 構成が含まれるようになり、PR の HEAD を pr という名称のローカル名前空間にマッピングするようになります:

1
2
3
4
    [remote “upstream”]
url = git@github.com:docker/libswarm.git
fetch = +refs/heads/*:refs/remotes/upstream/*
fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*

リファレンスを使用して、単一プルリクエストをフェッチする

お使いの .git/config 内に fetch エントリーをセットアップせず、単に素早くプルリクエストに達したい場合は、単一のコマンドが使えます:

  • Stash における、単一 PR の checkout:
    1
    git fetch refs/pull-requests/your-pr-number/from:local-branch-name
    
    
  • Github における、単一 PR の checkout:
    1
    git fetch refs/pull/your-pr-number/head:local-branch-name
    
    

上記を頻繁に使用しているのであれば、git alias を作成する事で、このプロセスをストリームライン化できます:

1
2
3
4
5
# For Stash
git config alias.spr ‘!sh -c “git fetch origin pull-requests/${1}/from:pr/${1}” -‘

# For Github
git config alias.gpr ‘!sh -c “git fetch origin pull/${1}/head:pr/${1}” -‘


このエイリアスを設定したら、プルリクエストのフェッチも次のようにシンプルな内容になります (inuit に感謝):

1
git spr 100

結論

是非今回の内容を活用して下さい!結局の所、一旦シンプルなエイリアスをいくつか作成したり、あるいはお使いの .git/config に適切な refspecs を追加すれば、同僚あるいはコントリビューターの作業内容の記録も簡単になります。何か質問等ありましたら、次の Twitter アカウント @durdn あるいは @AtlDevtools までご連絡下さい!

一人が優秀なのは簡単ですが、素晴らしい結果を出すにはチームワークが必要です。

Git Essentials ソリューションで、チームの作業効率を改善できるツールをお探し下さい。


*本ブログは Atlassian Blogs の翻訳です。本文中の日時などは投稿当時のものですのでご了承ください。
*原文 : 2014 年 8 月 12 日投稿 "Pull request proficiency: Fetching abilities unlocked!"