
GitHubの公式コマンドラインツールであるhubの存在を知り、最近使い始めている。いろいろな作業がコマンドからできてとても便利なのだが、フォーク元のリポジトリにプルリクエストを送るところで詰まってしまった。フォーク元のリポジトリを parent/repo、フォークして作られたリポジトリを child/repo としたとき、parentのmasterブランチ(parent:master)にプルリクエストを送りたかったのだが、 hub pull-requestとしたときのプルリクエストの宛先が child:masterになってしまった。
hub forkをしておくことが必要
この原因は、hub forkをしていなかったことにある。今回の場合、GitHubの画面上でリポジトリをフォークし、作成されたchild/repoをgit cloneして使っていたところで、hubについて知り使い始めた。しかしドキュメントの使用例では、フォークの段階からhub forkを使うことが前提になっている。フォーク元のリポジトリを parent/repo、フォークして作られたリポジトリを child/repo としたとき、以下のような流れで使う。
$ hub clone parent/repo //まずフォーク元をclone $ cd repo $ git checkout -b feature $ git commit -m "done with feature" //何か変更を加えてコミット $ hub fork --remote-name=origin //ここでフォーク $ git push origin feature $ hub pull-request
このとき、 hub fork --remote-name=origin は、リモートリポジトリを以下のように変更する。 --remote-name=originの指定があることで、originがchild/repoを指すようになり、parent/repoはupstreamという名前になる。
$ git remote -v origin git@github.com:child/repo.git (fetch) origin git@github.com:child/repo.git (push) upstream https://github.com/parent/repo (fetch) upstream https://github.com/parent/repo (push)
そして、hubはプルリクエストを送る際の宛先となるリモートリポジトリの指定がない場合、upstream -> github -> originという優先順位でリモートリポジトリを探し、見つかった場合はそこを宛先とする。((https://hub.github.com/hub.1.html のCONVENTIONの項目を参照。))このため、 事前にhub forkした状態で hub pull-requestとすれば、宛先はupstreamという名前で登録されているparent/repoのmasterブランチとなる。
既にフォークしたリポジトリでhubを使うには
今回は既にフォークしたリポジトリをgit cloneしてきたため、リモートリポジトリは以下のようになっていた。originという名前のものしかないため、プルリクエストの宛先がchild/repoのmasterブランチになるのも当然である。
$ git remote -v origin git@github.com:child/repo.git (fetch) origin git@github.com:child/repo.git (push)
これを回避するには、プルリクエストを送る際に以下のようなオプションをつける。-bが宛先のブランチ、-hが変更を加えたブランチを表す。remoteにparent/repoが登録されていなくても、hubコマンドがGitHubを探索してくれる。
$ hub pull-request -b parent:master -h child:feature
しかし、これから何度もプルリクエストを送るのであれば、hub forkと同様に、フォーク元のリポジトリをupstreamという名前でリモートリポジトリに登録してしまうのが良いだろう。これでオプションの指定なしでhub pull-requestが使えるようになる。
$ git remote add upstream https://github.com/parent/repo.git $ git remote -v origin https://github.com/child/repo.git (fetch) origin https://github.com/child/repo.git (push) upstream https://github.com/parent/repo.git (fetch) upstream https://github.com/parent/repo.git (push)