TL;DR originブランチはフォーク元のままにして、forkedを自分のリモートブランチとして使用する。

他人のGitHubのプロジェクトにプルリクエストを送る場合にGitHubへpull requestする際のベストプラクティス - hnwの日記で書かれている手順で行っていたのだけど、手順を憶えられなくて毎回ググっていたのでなんかいい方法がないかとやってたら以下のような手順に落ち着いた。

元のリポジトリをローカルに落とす

普通にgit cloneを使う:

$ git clone git@github.com:だれそれ/リポ名.git

GitHub上でフォークする前に、対象のリポジトリを直接ローカルに落として作業する。プルリクエストを投げれるような状態になるまでフォークする必要はない。

手元で修正し、コミット作成

$ cd リポ名
$ git checkout -b フィーチャーブランチ名  # フィーチャーブランチ作成
(ファイル編集)
$ git commit -am '変更内容'

修正したい内容をローカルで編集してコミットを作成する。その際にはブランチを切ってやる。

GitHub上で元のリポジトリを自分にフォーク

変更がいけそうだとなったら、プルリクエストを送るために元のリポジトリのページから[Fork]ボタンを押して、自分用のフォーク先のリポジトリを作る。

フォークしたリポジトリをリモートブランチ先として追加

GitHub上でフォークはしたけれど、ローカルに落としてあるリポジトリのリモート先originは元のリポジトリを指している。originはそのままにしておいて、例えばforkedという名前のリモートブランチを追加してやる:

$ git remote add forked git@github.com:自分/リポ名.git
$ git remote -v  # 確認
forked  git@github.com:自分/リポ名.git (fetch)
forked  git@github.com:自分/リポ名.git (push)
origin  git@github.com:だれそれ/リポ名.git (fetch)
origin  git@github.com:だれそれ/リポ名.git (push)

git remote set-url origin ...originを変更してしまうと後々元のリポジトリが更新されたときに追従するのが面倒なので、forkedという名前で自分のリポジトリを追加してやる。

フィーチャーブランチを自分のフォーク先にプッシュ

$ git push --set-upstream forked フィーチャーブランチ名

ローカルで作成していたフィーチャーブランチのリモート先をフォークした自分のリポジトリに設定する。

自分のリモートリポジトリにプッシュできたら、GitHubのプルリクエストを投げてやる。

コミットを更新

コードレビューなどでコミットに変更を加えた場合、再びプッシュする:

(フィーチャーブランチをチェックアウトしている状態で)
$ git push

フィーチャーブランチの自分のコミットは特に制限がない場合改変可能なので、改変した場合には--forceを使ってプッシュしてもOK:

(git commit --amend などでコミットを書き換える)
$ git push --force

元のリポジトリの更新に追従する

コードレビューの間に元のリポジトリのブランチが更新された時に追従したい場合には、単にoriginからpullしてやる:

$ git checkout master  # 基準のブランチをチェックアウト
$ git pull

フィーチャーブランチの分岐をきれいにするためにHEADに移動させるにはrebaseしてやる:

$ git checkout フィーチャーブランチ名
$ git rebase master
(コンフリクトは頑張って解消する。)
$ git push -f forked

プルリクエストがマージされた後の後始末

プルリクエストが取り込まれたならば、フォークした自分のリポジトリのフィーチャーブランチは不要になり[Delete branch]などというボタンが出るので、押してやると削除される。

またはコマンドライン上で行うには:

$ git checkout master  # フィーチャーブランチじゃないブランチに移動
$ git branch -d フィーチャーブランチ名  # ローカルからブランチを削除
$ git push forked --delete フィーチャーブランチ名  # フォーク先のリモートからも削除

他に送りたい変更もなくなったらフォーク先のリポジトリごとGitHubから削除してやってもいい。そうした後もローカルのoriginは元のリポジトリを指しているので、そのまま使い続けることができる:

$ git remote rm forked