CodeCommitを使用した開発におけるGit操作（Part1）

## はじめに

AWS CodeCommitを使用した開発では、Gitコマンドによる操作を頻繁に行います。ですが、私も含めGit初学者の方は、なんとな〜くコマンドを叩いている方も多いのではないでしょうか？

そこで本記事では、開発の流れに沿ったGitコマンドの使い方を解説していきます。

今回想定している開発の流れは大まかに以下の通りで、この流れの中で登場するGitコマンドについて紹介していきたいと思います。なお、以下の流れではGitのブランチ機能を使用した運用方法であるGit-flowを活用した開発を前提としています。

```mermaid
graph TB
  Start([CodeCommitにリポジトリを作成])-->B([リポジトリのクローン])
  B-->C([ブランチを切る])
  C-->D([コードの編集])
  D-->E([ステージング])
  E-->F([コミット])
  F-->G([プッシュ])
  G-->H([プルリクエスト])
  H-->I([マージ])
```

※本記事の内容は、2023年9月時点のものです。AWS CLIやGitのバージョンの違いなどが発生する場合があります。

## 対象者

- CodeCommitを使用した開発プロジェクトに参加している方
- Git初学者の方

## 準備

CodeCommitのリポジトリでソースコードを管理する場合、GRC(git-remote-codecommit)を使用すると、AWSアカウントの認証情報だけを設定しておくだけで、CodeCommitにアクセスできます。

またGRCの場合、1つのGitクライアント(自分のPCなど)から、別アカウントのリポジトリなど複数のリポジトリを使用できます。使用する際は、後ほど説明するプロファイルを切り替えることで、それぞれのAWSアカウントの認証情報で、それぞれのCodeCommitにアクセス可能になります。

まずは、それらの設定をしましょう！

### Python3とAWS CLIのインストール
```git-remote-codecommit```は```pip```を使用してインストールするので、Python3とAWS CLIが必要になります。

まず、以下の手順を参考にPython3をインストールしてください。Pythonの場合は、Pythonの[ダウンロードページ](https://www.python.org/downloads/)からインストーラーをダウンロードしても問題ありません。
[git-remote-codecommit を使用して AWS CodeCommit への HTTPS 接続をセットアップする手順 - AWS CodeCommit](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-git-remote-codecommit.html#setting-up-git-remote-codecommit-prereq)

次に、以下の手順を参考にAWS CLIをインストールしてください。
[AWS CLI の最新バージョンを使用してインストールまたは更新を行う - AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions)

Python3とAWS CLIがインストールされたら、```pip```コマンドを使用し以下のコマンドを実行してください。

```shell
pip install git-remote-codecommit
```

### プロファイルの設定
次に、プロファイルを設定し、コマンドラインからCodeCommitにアクセスできるようにします。まずは以下の手順を参考に、AWS IAMのコンソール画面で、IAMユーザーの認証情報となるアクセスキーを取得しておきます。
[AWS アカウントとアクセスキー - AWS Tools for PowerShell](https://docs.aws.amazon.com/ja_jp/powershell/latest/userguide/pstools-appendix-sign-up.html)

アクセスキーを取得したら、以下のコマンドでプロファイルを作成します。

```shell
aws configure --profile [プロファイル名]
```

- ```[プロファイル名]```：任意の値
- ```AWS Access Key ID```：アクセスキーの値
- ```AWS Secret Access Key```：シークレットアクセスキーの値
- ```Default region name```：CodeCommitのあるリージョン名(例: 東京リージョンならば、```ap-northeast-1```)
- ```Default output format```：何も入力しない

プロファイルが作成できたら、以下のコマンドで確認しましょう。

- LinuxまたはmacOSの方：
```shell
cat ~/.aws/credentials
```
- Windowsの方(```USERNAME```ディレクトリ配下で)：
```
type .aws\credentials
```

※認証情報ファイルは、LinuxやmacOS では```~/.aws/credentials```に、Windowsでは```C:\Users\USERNAME\.aws\credentials```にあります。(```USERNAME```はご自身のユーザー名です。)

上記のコマンドを実行して、先ほど作成したプロファイルの情報が表示されていれば、成功です。

ここまでできれば、準備OKです！


## CodeCommitにリポジトリを作成

CodeCommitを開き、「リポジトリを作成」からリポジトリを作成します。

プロジェクトによっては、リポジトリのクローンから始める場合もありますし、他のリポジトリの情報をコピーして始める場合もあります。その場合は、リポジトリのクローンから見てください。


## リポジトリのクローン(```Clone```)

### クローン(```Clone```)

```Clone```とは、ローカルの作業ディレクトリにリモートリポジトリ(ここではCodeCommitのリポジトリ)を複製することです。```Clone```には、以下のコマンドを使用します。

```shell
git clone codecommit://[プロファイル名]@[リポジトリ名]
```

なお、```[プロファイル名]```には、準備のときに作成したプロファイル名を、```[リポジトリ名]```には、対象のCodeCommitのリポジトリ名を入れます。


### プル(```Pull```)

すでにローカルリポジトリが存在し、最新コードを反映したい場合には、```Pull```することでローカルリポジトリをリモートリポジトリの情報に更新できます。

まずは、以下のコマンドでリモートリポジトリを追加しましょう。

```shell
git remote add origin codecommit://[プロファイル名]@[リポジトリ名]
```

このコマンドにより、リモートリポジトリを```codecommit://[プロファイル名]@[リポジトリ名]```ではなく、```origin```で指定できるようになります。またこの場合、```origin```以外の文字列を使用すれば、他のリモートリポジトリも追加できます。

次に、以下のコマンドで、追加したリモートリポジトリ(```origin```)とブランチを指定して、```Pull```しましょう。

```shell
git pull origin [ブランチ名]
```

なお、```[ブランチ名]```を省略した場合には、現在いるブランチ(カレントブランチ)が入ります。

これで、コードの編集を開始できます！と言いたいところですが、まず以下のコマンドでご自身のカレントブランチを確認してください。


### ブランチの確認

```shell
git branch
```

おそらく、```main```か```develop```ブランチにいると思います。

<details><summary> 各ブランチの特徴がわからない方はこちら</summary>

```main```ブランチは、リモートリポジトリを作成した時点で自動的に作成されるデフォルトブランチで、開発プロジェクトにおける```main```ブランチは本番環境の運用のために使用されるブランチです。

そのため、リリース中のサービスなどに影響を及ぼさないよう```main```ブランチ上でコードを修正したりすることはありません。そこで、```develop```ブランチと呼ばれる、最新コードを管理するための開発の中心となるブランチを、```main```ブランチから派生させます。

ですが、この```develop```ブランチも```main```ブランチ同様に、このブランチ上でコードを修正したりすることはありません。あくまでも、本番環境と開発中の環境を切り分けるために設けるブランチで、機能の開発や修正のための実際に作業を実施するブランチは、この```develop```ブランチからさらに派生させた```feature```ブランチと呼ばれるブランチ上で行います。

</details>


## ```feature```ブランチの作成

### ブランチの作成

開発プロジェクトでは、「ブランチを切る」と言ったりしますが、カレントブランチを元にして```feature```ブランチを作成する場合は、以下のコマンドを実行します。

```shell
git branch feature_xxx
```

派生元のブランチを指定したい場合は、```feature_xxx```の後ろに、派生元のブランチ名を入れてください。

:::note warn
```feature_xxx```はご自身のプロジェクトにおける命名ルールに則ってください。プロジェクトによって、```feature```の後は、```_```や```-```や```/```だったりしますが、その後の文字列は作業内容がわかるような名前やバックログ名などが入るようです。
:::


### ブランチの切り替え

ブランチを作成したら、そのブランチに移動しましょう。ブランチを作成してもブランチが切り替わっているわけではないので、以下のコマンドでブランチを切り替えます。

```shell
git switch feature_xxx
```

ちゃんと移動できたかどうかは、```git branch```で確認してください。


### ブランチの作成＆切り替え

ちなみに、ブランチの作成と切り替えを同時に行うこともできて、その場合には```-c```オプションを付けて、コマンドを実行します。

```shell
git switch -c feature_xxx
```

こうしてはじめて、コードを編集し機能の実装や修正作業を開始できます。


## ステージング(```Add```)

### Gitにおけるコードの在り処

コードの修正が完了したら、ステージング環境にその修正したファイルを登録します。

<details><summary> Gitにおけるコードの格納場所があやふやな方はこちら</summary>

Gitではコードの格納場所ごとにいろんな名前が付いていますので、それらをおさらいしましょう。

|場所|説明|
|:--|:--|
|リモートリポジトリ|AWS CodeCommitなど、ネットワークに接続されたサーバ上にあるリポジトリのことです。複数人で共有できます。|
|ローカルリポジトリ|「リモート」に対して「ローカル」なので、自分のPCなどにある自分専用のリポジトリのことです。```git clone```した場合は、指定したリモートリポジトリが複製されます。|
|ワーキングツリー|Gitで管理されている、実際に作業をしているディレクトリのことです。つまり、作業中のファイルパスのことを指します。|
|ステージング環境(インデックス)|ワーキングツリーで作業した変更(ローカルリポジトリとワーキングツリーの差分)を一時的に登録しておく場所です。ローカルリポジトリからリモートリポジトリの修正の反映は、このステージング環境を介して行われます。|

</details>


### 差分(```Diff```)の確認

```Add```する前に、以下のコマンドを実行しておきましょう。

```shell
git diff
```

これは、ローカルリポジトリとワーキングツリーの差分を確認するためのコマンドです。自分が修正した内容や範囲を把握できます。

:::note warn
```git diff```で自分が修正したファイル以外の内容が表示されるのであれば、他のファイルに何か余計な操作をしたことになります。(例えば、コードフォーマッターを全ファイルに適用したとか。)
:::

本当にその変更でいいのか確認するために、```git diff```コマンドを実行する癖をつけましょう。

### 変更したファイルをステージング環境に登録する

コードの修正が完了し、差分を確認して問題なければ、以下のコマンドで作成や修正、削除した(総じて変更を加えた)ファイルをステージング環境に登録(```Add```)します。

```shell
git add .
```

ただし、上記のコマンドの場合は、変更範囲すべてが```Add```されます。特定のファイルのみ```Add```したい場合は、以下のように対象のファイルのファイルパスを指定します。

```shell
git add [ファイルパス]
```

```Add```したいファイルが複数ある場合は、```[ファイルパス1] [ファイルパス2] ...```のように続けて書いてください。


## コミット(```Commit```)

### ```Add```したファイルをローカルリポジトリに登録する。

```git add```でステージング環境に登録したファイルを、次はローカルリポジトリに登録します。

```shell
git commit -m 'コミットメッセージ'
```

```コミットメッセージ```には、作業した内容などを簡潔に書きます(例：△△機能を実装)。これも、```feature```ブランチの命名ルールと同様にプロジェクトのルールに則りましょう。

また、```Commit```は次の章で行う```Push```までに複数回実行できます。例えば、△△機能を実装するにあたって、□□機能と◇◇機能の2つの機能を先に実装しなければいけないなどの場合に、それぞれの機能の実装ごとに```Commit```しておくこともできます。


## プッシュ(```Push```)

### ローカルリポジトリのコミット履歴をリモートリポジトリに反映する

```Push```とは、ローカルリポジトリのコミット履歴をリモートリポジトリにアップロードすることです。```Push```時は、リモートリポジトリのブランチ名を指定して行います。

```feature```ブランチを切って作業した内容を```Push```する場合は、```Push```先のブランチは、ローカルで作成した```feature```ブランチ名を指定してください。

```shell
git push -u origin feature_xxx
```

:::note warn
```Push```前は、リモートリポジトリに対象のブランチは作成されていませんが、その状態で```Push```すると、自動的にそのブランチを作成します。ですので、ローカルで切ったブランチ名を指定してあげれば、同じ名前でリモートのブランチが作成されます。
:::

:::note warn
初回```Push```時に```-u```オプションを付けることで、次回以降の```Push```は```git push```のみで、```feature_xxx```ブランチを指定しての```Push```とみなされます。```-u```とは、```--set-upstream```の省略形で、```Push```対象のリモートリポジトリのブランチを上流ブランチとして指定するために使用します。```Push```はこの上流ブランチを対象として行われます。
:::


## プルリクエスト(```Pull Request```)

### リモートリポジトリにコードの変更を反映する

```Pull Request```とは、ローカルリポジトリでの変更(```Push```した内容)をリモートリポジトリに反映するために、他の開発メンバにレビューやマージ(```Merge```)を依頼することです。よく、「プルリク」と言われてます。

:::note warn
レビューとは、他の開発メンバにコードの修正が適切かどうかチェックしてもらうことで、```Merge```とは、コードの変更内容を取り込むことです。今回の場合では、```feature```ブランチでの変更内容を```develop```ブランチに取り込むことになります。
:::

```Push```した内容が自分以外の誰の目も介さず、```Merge```されてしまうと、思わぬバグを引き起こしてしまう可能性もあります。なので、```Merge```される前に、他のメンバにレビューを行ってもらうことで、コードの品質をより向上させることができるようになります。


### CodeCommit上でのプルリクの出し方

CodeCommitのコンソール画面で対象のリポジトリを開きます。次に、「ブランチ」タブから、```Push```したブランチ(```feature_xxx```ブランチ)を選択し、「プルリクエストの作成」をクリックします。
![プルリク前の画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/473a70be-72fd-8342-f34b-6aaf46fd0bc8.png)
すると、以下のように```develop```ブランチに```feature_xxx```ブランチの内容を```Merge```しようとしていることがわかります。
![プルリクエストの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/3fbc76ac-cc53-316c-131e-0a12b1da7971.png)
詳細には、適切な「タイトル」と「説明」を入力します。

また、下にスクロールすると、今回のコードの変更箇所が確認できます。特に問題なければ、一番下の「プルリクエストの作成」をクリックします。
![変更範囲.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/5fb4ea06-6380-e01e-0175-ac20d9d7ff97.png)
画像の例だと、```index.html```の11行目を修正したということがわかります。

ここまでが、開発者として実際に作業する内容ですが、レビュアーの目線でマージまで行ってみたいと思います。

先ほど作成されたプルリクは、「プルリクエスト」タブから確認できます。
![レビュアー画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/cddf3d85-eb1d-8aac-7570-0218fe345859.png)
コードの変更がこの内容で問題なければ、右上の「マージ」をクリックします。一方、コードの変更に問題があれば、コメントを記載することもできます。(対象のファイルの対象の行にカーソルを合わせてクリックすると、コメントを入力できます。)

レビューにより指摘があった場合は、開発者は指摘箇所の修正を行い、再び同じブランチに```Push```すれば、レビュアーは改めてコードの変更を確認できます。

最後に、```Merge```を行いましょう。「マージ」をクリックすると、以下の画面に遷移します。
![スカッシュマージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/7b3b270d-7b4e-6c8d-7bd8-2cf430ff59ac.png)
マージの種類を選択できますが、ここでは複数のコミットを１つにまとめてリポジトリの履歴を簡素にするために、「スカッシュしてマージ」を選択します。

それぞれの```Merge```の説明は以下を参考にしてください。
[AWS CodeCommit リポジトリでプルリクエストをマージする - AWS CodeCommit](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/how-to-merge-pull-request.html)

下にスクロールし、「作成者名」と「Eメールアドレス」を入力したら、一番下の「プルリクエストのマージ」をクリックします。
![マージ完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506277/5b51cc72-1c4a-bde5-9808-de8c811ff531.png)
なお、「マージ後にソースブランチ feature_xxx を削除しますか?」にチェックが入っていますが、```feature```ブランチは作業内容やバックログ単位で作成されるものなので、```Merge```後は不要なブランチになります。なので、```Merge```時に削除します。

これで、ローカルで作業した内容が無事```develop```ブランチに取り込まれました！


### さいごに

今回、開発の流れに沿って、よく使用するGitコマンドをまとめてみました。当初はよく分からず行っていた操作でも、改めて何を行っているのか整理するのは大事だと感じました。

そして実は、今回の記事ではまだ説明できていないのですが、リベース(```Rebase```)というよく行う操作があります。この操作についても追々記事にできたらなと考えていますので、乞うご期待ください。


## 参考
本記事を執筆するにあたって、参考にしたページを以下に記載いたします。
- Git関連
  - [なぜdevelopブランチは必要なの？ · カウル Tech Blog](http://techblog.housmart.co.jp/2016/06/22/git-workflow/)
  - [git を初めて使う時 コミット→プッシュ→マージ　の流れ - Qiita](https://qiita.com/yukiyoshimura/items/7aa4a8f8db493ab97c2b)
  - [５分で理解【Git入門】ワークツリーとインデックス | ５分で理解できる技術録 | Yuji's Weblog](https://u-tan-web.com/git-worktree-index/)
  - [git push --set-upstream origin masterって毎回聞かれるのをやめる - Qiita](https://qiita.com/inusukiii/items/e107b91a58f8250838da)
  - [Gitではじめるバージョン管理 〜ローカルリポジトリでファイルを管理してみよう〜 - Hivelocity (ハイベロシティ) デジタルでビジネスを最適化](https://www.hivelocity.co.jp/blog/34777/)
  - [ローカルリポジトリとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word18802.html)
  - [リモートリポジトリにプッシュする｜サル先生のGit入門【プロジェクト管理ツールBacklog】](https://backlog.com/ja/git-tutorial/intro/09/)
  - [Git-flowをざっと整理してみた | DevelopersIO](https://dev.classmethod.jp/articles/introduce-git-flow/)
- GRC関連
  - [AWS CodeCommitの使い方](https://zenn.dev/satopi/articles/2023-01_usage-of-codecommit)
  - [AWS CodeCommit リポジトリに接続する - AWS CodeCommit](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/how-to-connect.html)
- プロファイル関連
  - [AWS CLI を設定する - AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html)