【Git初心者へ送る記事③】海外テック企業に行けるかも!? GitHub OSS開発についての図解

本記事はQmonus Value Streamの投稿キャンペーン記事です。
## OSS開発ってなんぞや？？
これができるようになればエンジニア中級者以上と言ってもいいのではないのでしょうか？？

そもそもオープンソースソフトウェア（OSS）というものはソースコードが公開されていて、**誰でも閲覧、利用、修正、再配布ができる**ソフトウェアのことです。そして、OSS開発はこのようなソフトウェアの開発に参加することを指します。


## OSS開発 Flow :ocean:
```mermaid
graph TD
    A[元のOSSリポジトリ]:::originalRepo -->|Fork| B[あなたのFork]:::yourFork
    B -->|Clone| C[ローカルリポジトリ]:::localRepo
    C -->|ブランチ作成| D[新機能開発/バグ修正]:::development
    D -->|Commit| E[ローカルの変更]:::localChanges
    E -->|Push| B
    B -->|Pull Request| A
    A -->|レビュー| F{承認?}:::review
    F -->|Yes| G[マージ]:::merge
    F -->|No| H[フィードバック]:::feedback
    H --> D
    A -->|Sync| I[最新の変更]:::sync
    I -->|Pull| C

    classDef originalRepo fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff;
    classDef yourFork fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
    classDef localRepo fill:#FFC107,stroke:#333,stroke-width:2px,color:#fff;
    classDef development fill:#FF5722,stroke:#333,stroke-width:2px,color:#fff;
    classDef localChanges fill:#9C27B0,stroke:#333,stroke-width:2px,color:#fff;
    classDef review fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
    classDef merge fill:#8BC34A,stroke:#333,stroke-width:2px,color:#fff;
    classDef feedback fill:#F44336,stroke:#333,stroke-width:2px,color:#fff;
    classDef sync fill:#03A9F4,stroke:#333,stroke-width:2px,color:#fff;

    linkStyle default stroke:#333,stroke-width:2px;
```

## 手順 :1234:
ここからは誰でもできるOSS開発の手順を簡単に解説していきます。
※ローカルの準備に関しましては初心者用に一つのやり方を示しているだけですので、自分のやり方があるのであればそれを優先してください。

また、こちらの動画は自分がよく学習用に観ているYoutubeチャンネルなのですが、わかりやすい解説がありましたので紹介いたします。日本語字幕ついてるのでご安心を:relaxed:

https://www.youtube.com/watch?v=yzeVMecydCE

### 前準備として、新規ディレクトリ作成でgit initして移動しておく。
```
mkdir my_project
cd my_project # これを実施しないと別の場所にcloneしてしまう
git init
```

## 次に参加するプロジェクトを選定しましょう
興味のあるオープンソースプロジェクトを探します。以下の方法でプロジェクトを見つけることができます。

### OSSコミュニティサイト: Awesome Lists

https://github.com/sindresorhus/awesome

### First Timers Only: 初心者向けのプロジェクトならこちら

https://www.firsttimersonly.com/

## プロジェクトが決まればgit操作してきます
### **①参加プロジェクトのリポジトリをフォークしてリモートリポジトリをGitHubに追加**
これはGitHub上で実施します。作成したときにつくられるURLを必ず確認しましょう。

### **②リモートリポジトリをローカルにclone**
```bash
git clone リポジトリURL # ここでGitHub URLを使う
cd リポジトリ名 # クローンしたディレクトリに移動
```

### **③フォーク元リポジトリをローカルリポジトリに設定**
```bash
git remote add upstream フォーク元リポジトリURL
```

これによりフォーク元リポジトリをローカルリポジトリの**2つ目のリモートリポジトリ(upstream)** として設定します。**forkしてcloneした場合、1つ目のremoteであるoriginは自動的に設定されるため、手動でgit remote addする必要はありません。**

※1つ目は`origin`、2つ目のOSSフォーク元のリモートリポジトリは`upstream`とすることが一般的です。また、ローカルリポジトリのbranchに対応しているリモートリポジトリのbranchを上流branchといいます。

`git branch -vv`でローカルbranchに対応している上流branchを確認できます。

## 一旦ここで整理しましょう :writing_hand:
冒頭の解説図を確認して欲しいのですが、fork元の`upstream`をリモートに設定する主な理由はなんでしょうか？
### 以下が、主な理由です

1. 最新の変更の取得：他の開発者がフォーク元のリポジトリにコミットした場合、`upstream`から最新の状態を取得するため。これによりプルリクエストを作成する前に、`upstream`の最新変更を取り込むことで、コンフリクトのリスクを減らせます。

4. 大規模な変更の追跡：元のプロジェクトで行われた大きな変更や新機能の追加を簡単に確認するため

確認ですが`upstream`からの更新を取得するには、以下のコマンドを使用します：

```bash
git fetch upstream
git checkout main
git merge upstream/main
```

これにより、フォーク元の最新の変更をあなたのローカルの`main`ブランチに取り込むことができます。その後、必要に応じて自分のGitHub上のフォークにプッシュすることで、フォークも最新の状態に保つことができます。

### **④ローカルリポジトリでbranchを切って開発を進めてcommitしていく**
全体の流れの記事ですので詳細は省きますが、基本的に開発はmainではなく開発用のブランチを切って進めていきます。

```bash
git checkout -b feature-branch # 新しいブランチを作成し、そこに切り替え
# 開発作業を行う
git add .
git commit -m "コミットメッセージ"
```

### **⑤push前に確認すること**
 ✅ Aパターン
もしここで**フォーク元のリモートリポジトリのメインブランチがcommitされて伸びている(Fast-Forwardではなくなっている)** ならば、先にローカルをメインに統合する必要があります。

```bash
git checkout main # メインブランチに移動
git pull upstream main # フォーク元の最新変更を取得
git checkout feature-branch # トピックブランチに戻る
git rebase main # トピックブランチをメインブランチにリベースする
```

✅ Bパターン
**フォーク元のリモートリポジトリのメインブランチがcommitされておらず綺麗な状態**であれば、このまま次に進みましょう。

## ⑥リモートリポジトリ(origin)に現段階のローカルリポジトリの開発を反映させるためにpushする
```bash
git push -u origin feature-branch
```
ただし、Aパターンで説明したように、フォーク元のリモートリポジトリのメインブランチが伸びていた場合はローカルでリベースしているため、以下のコマンドを使用します：

```bash
git push --force-with-lease origin feature-branch
```

rebaseによりエラーが発生するので、強制的にプッシュするために`--force-with-lease`オプションを使用します。これは`--force`よりも安全なオプションです。

また、rebase中にコンフリクトが発生した場合は、ファイルを修正して`git add`してから`git rebase --continue`を実行して続行します。

### ⑦リモートリポジトリ内で反映した内容をmergeしてもらうためにpull requestを出す
こちらもGitHubサイト上で実施。しっかりとわかりやすくコメントを記載すること。

### ⑧pull requestが通ったらリモートリポジトリでmergeされる

### ⑨そのmergeされた状態をローカルリポジトリにpull(fetch&merge)する


```bash
git checkout main
git pull upstream main
```
メインが特に変更されていないなら、以下のようにpull rebaseすることもできます：

```bash
git pull --rebase upstream main
```

### ⑩開発に使用したtopic branchを削除する
```bash
git push --delete origin feature-branch # リモートブランチの削除
git branch -d feature-branch # ローカルブランチの削除
```

## おまけ `git rebase`について :point_up:
チーム開発においては度々登場する`git rebase`ですが、下図を見てもらうとわかりやすいのではないでしょうか？

要はローカルの自分の作業ブランチの元を最新のコミットに移動します。
これによりコミット履歴が直線上になって綺麗になります。

![スクリーンショット 2024-07-04 19.52.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492127/71a72eba-2524-50c1-f30a-2d0ad72a41f4.png)


## 最後に
「海外企業のOSS開発をしていて、企業からスカウトがきてそのまま海外のテック企業に入社した」なんて話もちょちょこ聞きます。OSS開発で貢献していくということは自分のスキルアップにもなるし、たくさんのチャンスがあるので、余裕のある方はどんどんチャレンジしていきましょう:rocket: