GitLabとEclipseのEgitでGitLab Flow運用をやってみよう

# はじめに
ブランチ戦略が決まったら結局何をやったら良いの？という疑問を掘り下げてみた。
CUIでやってみるのが一番理解が深まりそうだが、結局、プログラムを書く人がオペレーションするのはIDEなので、IDE上での操作を中心に運用方法を整理してみよう。

# GitLabのインストール
今回の目的はちゃんとしたGitLabを作ることではないので、以下の記事を参考にしながら手抜きで作る。GitLabを起動した後のメモリ使用量は2.5GB程度になるので、t2.mediumなEC2を用意しよう。

【Qiita】[Docker ComposeでGitLabを起動
](https://qiita.com/str416yb/items/2932052a6ead78c167e4)

ちなみに、テキトーに起動するとGitLab内のリンク動作があやしくなるので、URLだけはちゃんと設定する。本来はEIPとってRoute53でドメイン固定にするか、ALB/NLBあたりに頑張らせるかとかを考えるのだけど、面倒なので、今回はEC2起動時のパブリックDNSを使って起動することにしよう。EC2が再起動すると、ローカルリポジトリが迷子になるので、実運用では絶対にやってはいけない。

EC2のパブリックDNSをEC2自らが取得する方法は↓これ。
【AWS公式】[インスタンスメタデータの取得](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html)

以下の様に環境変数を定義して、

```shell
$ export EXTERNAL_URL=`curl http://169.254.169.254/latest/meta-data/public-hostname`
```

こんな感じでdocker-compose.ymlに渡してあげる。

```YAML:docker-compose.yml
version: "3.7"
services:
  gitlab:
    container_name: gitlab
    image: gitlab/gitlab-ce:latest
    restart: always
    volumes:
      - ".conf:/etc/gitlab"
      - ".log:/var/log/gitlab"
      - ".data:/var/opt/gitlab"
    ports:
      - "9001:80"
      - "10022:22"
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url "http://${EXTERNAL_URL}"
        nginx['listen_port'] = 80
        nginx['listen_https'] = false
        gitlab_rails['time_zone'] = 'Asia/Tokyo'
```

これで

```
$ docker-compose up
```

で起動すればGitLabの準備完了だ！

基本的にWebのGUIなので重要なのは80番ポートのポートフォワードだが、SSHで ```git clone``` するのであれば、```"10022:22"``` のポートフォワードが必要なので留意しておく。

# GitLabの日本語化
英語じゃ嫌よ、と言う人はこの手順で日本語化。

右上のメニューから
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/de311fe6-3f73-de57-0c62-1ac5f0f72cf1.png)

「Settings」を選択して
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/da4716bf-f3b6-eb5a-8355-d98129f4753f.png)

出てきた画面のサイドバーから「Preferences」を選択して
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/04d5ff5c-a8d6-7ec4-3d92-270669da2adb.png)

下の方にスクロールしていって、「Localization」セクションの「Language」で日本語を選択して、「Save changes」ボタンを押せば完了！
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/7ad1bf46-b833-5772-21d5-bbacf2760560.png)

# リポジトリのチェックアウト
## リポジトリURIのコピー
GitLabのプロジェクトの画面で、以下のボタンを操作してURIをコピーする。
![キャプチャ9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/27f20cb4-7651-28cf-0d69-4b3cb60fa945.png)

## Gitリポジトリービューの表示
Eclipseのメニューの「ウィンドウ」⇒「ビューの表示」⇒「その他」を選択。
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/2dfd93ea-a99f-717c-0f51-234ac5af53f7.png)

開いたダイアログで、「Git」でフィルタし、「Gitリポジトリー」を選択。
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/5350a783-a486-2a5a-2449-69f0f9cd9cfa.png)

↓のようなビューが開けば成功。好きなところに配置しておく。
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/ed60c50c-b41a-3512-0258-974957829d20.png)

## リポジトリのチェックアウト
Gitリポジトリービューのメニューアイコンで矢印の点のものを選択し、出てきたメニューから「リポジトリーのクローン」を選択。
![キャプチャ8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/8cf131ff-0558-3e04-5bc3-7c149a4de77d.png)

開いたダイアログで、URIにコピーしたURIを貼り付け。「ホスト」と「リポジトリー・パスは」オートフィルされる。ポートは80から変更していないなら指定は不要。
認証は、GitLabの認証IDとパスワード。「セキュア・ストアに保管」にチェックを入れていると次回以降はオートフィルされる。
![キャプチャ10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/f0d7312f-3f81-2e35-d747-5585c9506813.png)

以降はデフォルトのまま「次へ」を選択していけば、以下の様にGitLabのリポジトリがcloneされてローカルで参照可能になる。
![キャプチャ11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/deb16190-be85-084e-b06c-2f8a358b1886.png)

## プロジェクト・エクスプローラーの設定
上記のままだと操作がしにくいので、プロジェクト・エクスプローラーでも編集可能なように設定をする。

プロジェクト・エクスプローラー上で右クリックをして「インポート」を選択。
![キャプチャ12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/020246d4-7e02-8129-d6d4-4956c2c18873.png)

開いたダイアログで、「Git」でフィルタして「Gitからプロジェクト」を選択し、「次へ」ボタンを押す。
![キャプチャ13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/fdb9123d-89ab-aac0-b339-e9b4fe7e6388.png)

開いたダイアログで「既存ローカルリポジトリー」を選択して「次へ」ボタンを押す。
![キャプチャ14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/dd317d51-6056-9d2d-d302-cf1fc91ac6c9.png)

開いたダイアログで、前の手順でcloneしたgitのローカルリポジトリを選択して「次へ」ボタンを押す。
![キャプチャ15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/11d62ec1-816d-0324-ff15-3fd796395d14.png)

開いたダイアログで、「一般的なプロジェクトとしてインポート」して「次へ」ボタンを押す。
もしかして、Mavenプロジェクトだった場合は「新規プロジェクト・ウィザードを使用してインポート」しないといけないかもしれない。
![キャプチャ16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/1733a55b-bf71-3f56-db46-4b550060bfa7.png)

あとは、適当にプロジェクト名をつけて「完了」すれば良い。
![キャプチャ17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/d80b7368-963f-ec9c-c5ca-0a8a750c0012.png)

プロジェクト・エクスプローラーにGitのローカルリポジトリが入った！
![キャプチャ18.PNG.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/135eeee5-a73d-6cd3-a518-b1229e8bf69a.jpeg)

# Gitの概念を知っておく
色々といじり倒す前に、Gitの概念をちゃんと知っておかないと痛い目にあう。
以下の記事が分かりやすい。

【Qiita】[【Git】リモートからの取得とリモートへの反映で行っていること(fetch,pull,push)](https://qiita.com/forest1/items/db5ac003d310449743ca)

記事中で「リモート追跡ブランチ」と書かれているものは、Eclipseでは「リモート・トラッキング」と表現されている。
以下はGitリポジトリービューでの表示例。リモート・トラッキングにはissue01があるが、ローカルには無い。これは、**fetchはしてきたが、checkoutはしていない**という状態である。この状態では編集ができない。
![キャプチャ19.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/674d0b63-ceee-36a8-5b13-1e65af341407.png)

ヒストリーで見るとこんな感じ。色と、```origin```が付与されているかどうかで見分けがつく。
![キャプチャ20.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/7f1ab3f7-5911-8152-e9d3-fa6dc2cfacc7.png)

逆に、ローカルでCommitしていても、Pushしていなければリモートに反映されないので注意が必要。

この辺りの概念を踏まえて、GitLabとEclipseで行うオペレーションを整理する。

# featureブランチにIssueを登録する
GitLab Flowの原則は、masterブランチからfeatureブランチを分岐させて開発を行うことである。
GitLabでは、課題(Issue)をもとにブランチを作成するのが基本らしい。

## 課題(Issue)の登録
プロジェクトのサイドバーから「課題」を選択する。
![キャプチャ21.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/ccad9365-1ea8-0b7d-cd46-40cb3d34cfc5.png)

開いた課題一覧の画面で「新規課題」のボタンを押す。
![キャプチャ22.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/b81c12dd-abca-6d3b-7a88-33be040617cc.png)

適当に課題を起票して「Submit 課題」ボタンを押す。
![キャプチャ23.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/07447654-0e32-8e78-6f7d-dd96be539236.png)
![キャプチャ24.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/c0b883ab-5919-1943-6f05-ba91381c08a9.png)

課題の詳細画面にある「マージリクエストとブランチを作成」の右にある▼のボタンを押して「ブランチ作成」を選択。ブランチ名を```feature/ブランチ名```にして、ソースを```master```にしてから「ブランチ作成」ボタンを押す。
![キャプチャ25.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/1ebe6b55-2a8a-12df-425e-22d8246c3248.png)

リポジトリのブランチ一覧を見ると、さきほど追加したブランチが表示されている。
![キャプチャ26.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/d3870fde-e64e-88a7-546b-86f29a27bbc6.png)

## Eclipseへの反映
当然、これはEclipse側には反映されていないので、Eclipse側のローカルリポジトリとリモート・トラッキングリポジトリに取り込みを行う。

Gitリポジトリービューで、対象のリポジトリを右クリックして表示されたメニューのプルを選択する。
![キャプチャ27.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/0ac45645-aef5-5948-33ab-6601a7012ae2.png)

すると、先ほど作ったブランチがPullされた旨のダイアログが表示される。
![キャプチャ28.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/0144422a-b7fa-166e-4a86-915f16facdfc.png)

Gitリポジトリービューを見ると、リモート・トラッキング側に追加したブランチが表示されるようになる。ただし、↑に書いた通り、これはまだローカルブランチまで反映されていない。
![キャプチャ29.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/62e5b540-302e-c7d4-d162-fad03bef63d9.png)

リモート・トラッキングにfetchされてきたブランチを右クリックして、表示されたメニューで「ブランチの作成」を選択する。これ、めちゃくちゃ分かりにくいけど、「ローカルブランチの作成」を意味するらしい……
![キャプチャ30.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/42280a9c-027f-ed40-f8f9-d50daf3d9eba.png)

次に表示されるダイアログは、特に何もいじらず「完了」ボタンを押す。
![キャプチャ31.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/08180f6a-0295-53c2-baa3-c45d6504d4e4.png)

すると、ローカルリポジトリにもPullしてきたリモート・トラッキングと同じ内容になる。
![キャプチャ32.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/fb611372-0965-67e4-820d-47616d24c1af.png)

# featureブランチを更新する
## 今回の変更の前提
今回の修正は以下のような内容とする。
これを、masterに書き戻すところまでやってみよう。

```shell:test.sh(変更前)
#!/bin/sh

echo "master"
```

```shell:test.sh(変更後)
#!/bin/sh

echo "master"

echo "feature/issue01"
```

## 更新したらまずはCommitする
上記の更新をしたら、まずはCommitをしてみよう。

プロジェクト・エクスプローラーの対象リポジトリのプロジェクトを右クリックして、表示されたメニューで「チーム」⇒「コミット」を選択する。
![キャプチャ33.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/ce879e0f-d8df-0614-c9ed-5cb3be04db1b.png)

Gitステージングのビューが開くので、Commitしようとしているブランチが正しいか確認し、「ステージされた変更」に対象ファイルが入っていることを確認したら「コミット」ボタンを押す。入っていなかったら「ステージされていない変更」から「ステージされた変更」にドラッグ＆ドロップする。
「コミット」ボタンは、その左の「コミット及びプッシュ」ボタンでも良いが、今回は状態も含めて確認するために一旦Commitのみにする。
あと、例では書き忘れたらコミット・メッセージが入っていないとエラーになるので注意。
![キャプチャ34.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/3e4e5ec0-d08c-6d4c-32e0-93ea7607253e.png)

こうすると、Gitリポジトリービューのブランチの表示に「↑１」という文字が現れる。
これは、まだリモートリポジトリにPushしていないものがあるということを意味する。
![キャプチャ35.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/b4baf948-76a7-6571-8712-55841f966aad.png)

次は、Gitリポジトリービューで対象のリポジトリを右クリックして「アップストリームへプッシュ」をする。
![キャプチャ36.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/d7fd4d64-3d82-e946-abd0-3a49ce371e68.png)

すると、プッシュ結果と、「マージリクエストするならここに来い」というリンクが表示される。
このリンクを踏むとEclipse内でブラウザが上がってうざいので、通常使っているブラウザにコピー＆ペーストしよう。
![キャプチャ37.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/7ae5d760-2ee9-9935-292c-7364021c48f0.png)

リモートリポジトリ側も確認してみよう。ちゃんと更新が反映されている！
![キャプチャ38.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/0dbe9876-2e03-2aa2-f050-10a2482c891b.png)

# featureブランチをmasterブランチにマージする
さて、課題からブランチを作ったのだから課題からマージができるのだろうと思うが、課題からマージリクエストとしようとするとなぜかブランチがもう一本できてしまうので、手動でマージリクエストをする。

プロジェクト画面のサイドバーから「マージリクエスト」を選択し、表示されたマージリクエストの一覧画面で「New Merge Request」ボタンを押す。
![キャプチャ39.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/449fe93a-6ded-c3d6-3462-55c5387a2aaf.png)

Source Branchの「ソースブランチを選択」のプルダウンから対象のブランチ(今回はfeature/issue01)を選択し、Target Branchは今回はそのままで問題ないはず。もし、```master```が選択されていないようであれば、```master```にして、「Compare branches and continue」のボタンを押す。
![キャプチャ40.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/64a6ed28-2476-a9e6-ccd2-935d9873a510.png)

マージリクエストの詳細はテキトーに入れて、「Submitマージリクエスト」のボタンを押す。
ソースブランチは消しちゃっても問題ないが、今回は一応消さないようにチェックを外しておく。
![キャプチャ41.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/fc2d4c6e-6f12-fca6-cec9-b19ee5e4c705.png)
![キャプチャ42.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/79804274-ac04-b728-4c28-06987215b2cf.png)

マージリクエストが送られたら、マージ可能なユーザが詳細画面に行き「Merge」ボタンを押す。
![キャプチャ43.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/59fb5dcd-fcbc-8b51-acbf-a88929cf781b.png)

マージ完了！普通はここからCI/CDが起動するから、実運用時はちゃんとコードレビューが終わってからマージするように。
![キャプチャ44.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/197fc555-45d1-1bd4-f504-cb81d80dcb24.png)

グラフを確認しても、ちゃんとfeature/issue01がmasterに取り込まれたグラフになっていることが分かる。
![キャプチャ45.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/846ec0f1-af97-93d5-ecf6-60106a174088.png)

なお、マージ前のレビューはWebからも行える。
詳細画面の「Web IDEで開く」ボタンを押す。
![キャプチャ46.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/579d81ba-de3b-2d2e-5f79-cefe456e80ee.png)

こんな感じでdiff確認のようなものができる。
小さいソースでやる分には良いけど、差分が多かったりしたらEclipseとかの方がレビューしやすいのではないかな、と思う。
![キャプチャ47.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/a03d27d0-78e1-a8c8-8c0b-558c5387dc97.png)

なお、マージ後のローカルリポジトリへの反映は、最初と同じようにPullすれば良い。
![キャプチャ48.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/22dbff16-fab4-8a5e-6c0f-812a635781bd.png)

# ここから後は
基本は同じ。pre-productionブランチなり、productionブランチなりにマージリクエストをすればよい。ブランチに合わせてCI/CDパイプラインを作っておけば、夢の「起動環境ごとの自動化」も実現可能。夢が広がる。

ちなみに、GUIは乏しいが、この記事で書いたことはCodeCommitでも行える。CodeCommitの場合、マージリクエストではなくプルリクエストという名称だが、中身は変わらない。たぶんGitHubも同じだと思う(GitHubは使ったことがない)。

masterが次期開発で汚れているときのhotfixのcherry-pickはどうやるべきなの？といった課題は出てくるので、追々検証して追記してみようと思う。