【超図解】OSSにPull Requestを出す時の備忘録

OSS(Open Source Software)のコミュニティー(本家)のリポジトリにPull Requestを出す時にいつも手順が分からなくなってしまいます[^procedure]。例によって調べながらやりますが、ページによって記載がまちまちだったりします。そこで備忘録として手順をまとめておくことで迷わずスムーズにPull Requestを出せる様にしておこうと思いました。また、ただGitのコマンドを羅列しただけの備忘録では無く、実際に[Vega Editor](https://github.com/vega/editor)というOSSにコントリビュートしてみた行程をまとめて残しておこうと思います。

:warning: GitHubを例に解説しますが、その他のGitベースのサービス(GitLab, BitBucket等)も基本的に(コマンド)操作は同じです。

# OSSのリポジトリをForkする
今回は[Vega Editor](https://github.com/vega/editor)というOSSにコントリビュートしてみようと思います。たまたま今回この記事を執筆するタイミングで修正箇所が有った為、選択したという次第です。Forkを実施するためにまずはOSSのGitHubのリポジトリ[^vegaeditor]にアクセスします。OSSのリポジトリを自分のGitHubアカウントにForkして自分リポジトリとして扱える様にします。Forkの方法は下図の赤丸の`Fork`ボタンをクリックするだけです。

<img width="1437" alt="fork.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/2787bf2c-691f-3e24-ca28-2d1eacf06b4d.png">

# Forkしたリポジトリのクローン
Forkしたリポジトリは`自分のユーザー名/リポジトリ名`[^repositoryname]という名前が付きます。このリポジトリにまず修正を反映します。修正作業を行うためにリポジトリをローカルにクローンします。下図の`Clone or download`をクリックします。ここで、パスワード認証(HTTP)かSSH認証によってURLが異なります。URL横のクリップボードマークをクリックすることでURLをコピー出来ます。

<img width="1437" alt="clone.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/442e9887-5b92-6748-9a4e-5000aacb21ed.png">

今回の検証に使っているリポジトリでは以下のコマンドになります。

```bash
git clone git@github.com:y-vectorfield/editor.git
```

# Upstreamブランチ情報の登録
これ以降登場する用語の早見表をまず掲載します。これは所謂どこのリポジトリを指しているかのエイリアスの様な物です。

|エイリアス|指しているリポジトリ|
|:---|:---|
|リモート(origin)|自分のアカウントのリモートリポジトリ[^origin]|
|ローカル|自分のローカル作業環境上のリポジトリ|
|upstream|OSS本家のリポジトリ[^upstream]|

それでは本家のリポジトリを`upstream`として`git config`に登録します。URLは本記事での例です。

```bash
git remote add upstream https://github.com/vega/editor
```

登録結果を確認します。

```bash
git config -l
```

末尾に以下の内容が追加されていれば成功です。

```config
remote.upstream.url=https://github.com/vega/editor
remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/*
```

# 修正を反映し、Commit & Push
<font color="RED">修正用のブランチに必ずスイッチ</font>してからローカルで修正を行い、まずリモートリポジトリに修正を反映させます。今回は`docker-compose.yml`にrestartオプションを追加する修正を行います。

:warning: OSSのコミュニティーによってContributionルール(ブランチ名の付け方、commitメッセージの書き方等を指定)を定めている場合はルールに則ります。

## 2024/1/1追記: 参考情報
TensorFlow, PyTorch, scikit-learnへのコントリビューション時の参考情報は以下

https://qiita.com/y-vectorfield/items/11f76b305a54a7e67179

## 2025/2/28追記: 参考情報
Microsoft製のOSSに個人でコントリビューション時の参考情報は以下

https://qiita.com/y-vectorfield/items/082a76c923f17f4e6d0b

```bash
$ git checkout -b add-restart-option
Switched to a new branch 'add-restart-option'
```

```diff
version: "3.7"
services:
  editor:
    init: true
    build: .
    ports:
      - "8080:8080"
    volumes:
      - "./src:/usr/src/app/src"
+   restart: "always"
```

この修正が反映されることで、マシーンの再起動後必ずコンテナが再起動する様になります。後はリモートにcommit & pushを実施します。

```bash
$ git add .
$ git commit -m "Add restart option into docker compose yml file"
$ git push origin add-restart-option
```

# Pull Requestをコミュニティー(本家)に提出
`Compare & pull request`をクリックします。Pull Requestに添付するコメントを入力する画面が表示されます。コメント後`Create pull request`をクリックし、提出します。

<img width="1437" alt="pull request.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/34500519-32d0-3701-6db4-3eb33a5a7aa0.png">

提出後、多くの場合テストやフォーマットチェックなどが実行されます。完了すると下図の様な表示となります。

<img width="1437" alt="completed.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/e0713eb7-cd99-2f03-a97c-fca0a312d015.png">

* 参考: [[実践] はじめてのPull Requestをやってみよう](https://qiita.com/wataryooou/items/8dce6b6d5f54ab2cef04)

# 無事Mergeされました
Pull Requestが無事`Merge`(採用)されました!!これでOSS本家のリポジトリに修正が反映されました。

![merged.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/524607ea-e676-df4a-899e-66b5f87a4129.png)

<img width="1437" alt="merged2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/074dbfca-f810-8adb-77a2-1666bf934ec7.png">

# Merge後のupstreamの内容をローカル, リモートに反映
無事Pull RequestがMergeされたので、その内容を`ローカル`と`リモート(origin)`に反映します。この行程は今後Pull Requestを出す時に、コミュニティーのリポジトリが更新されていた(手元のリポジトリが古い)場合にも実施します。

ローカルブランチが`master`にチェックアウトされて居ない場合はチェックアウトします。

```bash
git checkout master
```

まずupstreamの最新版の内容を`fetch`します。

```bash
git fetch upstream
```


`ローカルのmaster`ブランチに`upstream`の内容を`merge`します。

```bash
git merge upstream/master --ff-only
```

最後に`リモートのmaster`ブランチに更新を反映します。

```bash
git push origin master -u
```

下図の様にコミュニティーのリポジトリ(upstream)とリモートリポジトリが同じ状態になりました。

<img width="1437" alt="community.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/c20d533a-74dc-e339-2908-71bb32128178.png">

<img width="1437" alt="remote.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/7ac00e4f-992c-23d3-f5ba-66134dd1e537.png">

# まとめ
OSSのコミュニティーにPull Requestを出す手順を備忘録を兼ねてまとめてみました。これでGitの仕様が変更にならない限りは操作に困らなくなります。

# Reference
* [Github Fork Pull Request](http://kik.xii.jp/archives/179)
* [GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する](https://qiita.com/xtetsuji/items/555a1ef19ed21ee42873)
* [git pushのオプション -u とは](https://qiita.com/shumpeism/items/1b8027c8905ca826416d)

[^procedure]: 業務等で頻繁にPull Requestを出しておられる方には何でも無いことなのかもしれませんが、趣味でやっているため、どうしても断続的になりがちです。。。

[^vegaeditor]: 本記事の場合: https://github.com/vega/editor

[^repositoryname]: 筆者の場合: y-vectorfield/editor

[^origin]: 本記事の場合: https://github.com/y-vectorfield/editor

[^upstream]: 本記事の場合: https://github.com/vega/editor