Gitの基本②　Gitの設定方法と開発フロー

本記事ではGitの設定方法についてまとめていきます。
環境と前提は下記のようになります。

**環境**
・Windows 11
・git version 2.47.1.windows.1
・VSCode

**前提**
・Gitのインストールが完了した直後であること

## 設定方法

git bashを開きます。

これからユーザーネームとメールアドレスの登録を行います。
設定によってはGithubでのソースコード公開等を行うと個人の特定につながる可能性があるので注意してください。

まずユーザーネームを設定します。
（「yourname」としている部分は自分の名前を設定してください。）
```
git config --global user.name "yourname"
```

次にメールアドレスを設定します。
（「yourmailadress@domain.com」としている部分は自分のアドレスを設定してください。）
```
git config --global user.email "yourmailaddress@domain.com"
```

次にテキストエディタの設定を行います。
日本語の文字化けを防ぐためにutf8を設定します。
```
git config --global core.editor "vim -c 'set fenc=utf8'"
```

次に最初に作成されるブランチの名前を「main」に設定します。
```
git config --global init.defaultBranch main
```

ここまで設定できたらgitconfigファイルを確認しましょう。

```
less ~/.gitconfig
```

このように表示されるはずです。
確認ができたら、「q」を入力をし、lessでのファイル表示を終了します。
```gitbash
[user]
        email = yourmailaddress@domain.com
        name = yourname
[core]
        autocrlf = true
        editor = vim -c 'set fenc=utf8'
[init]
        defaultBranch = main
~
```

## ファイルの準備
デスクトップにgit_practiceという名前のフォルダを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/9002090b-12b5-2b2f-a5db-200fb942113f.png)

このフォルダをVSCodeで開きます。
VSCodeを開く⇒「ファイル」をクリックする⇒「フォルダーを開く」をクリックする⇒「git_practice」を選択する

## gitignorの設定
**git ignor**
…gitで特定のファイルやディレクトリを無視するために.gitignorファイルというものを使用します。
　この.gitignorファイルに無視したいファイルやディレクトリを記述することによって、不要な更新等を避けることができます。

git bashを開いて、下記コマンドを実行します。
.configディレクトリを作成し、その中にgitディレクトリを作成するコマンドです。 

```
 mkdir -p ~/.config/git 
```

次に、ignoreファイルを作成し、内容を記述するコマンドを実行します。
```
vim ~/.config/git/ignore
```

すると何も記述されていない状態のignoreファイルの中身が表示されるので、

キーボードの「i」を押下し、インサートモードにします。
下記のGitHubのURLからwindowsのgitignoreファイルの内容をコピーして、
gitbashで開いているignoreファイルにペーストします。

https://github.com/github/gitignore/blob/main/Global/Windows.gitignore

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/be87c502-b588-83b9-69af-72f42625e546.png)

ペーストができたら、「esc」エスケープキーを押して、「:wq」を入力⇒Enterでファイルの内容が保存されます


### リポジトリの初期化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/285db480-23f9-3100-5f49-969a16c724d4.png)
コマンドプロンプトを開き、git_practiceディレクトリの中でコマンドを実行できる状態にします。
（git_practiceがカレントディレクトリになります。）

コマンドプロンプトの開き方がわからない人向け↓
　まず、git_practiceディレクトリをファイルサーバで開き、パス入力欄に入力されているパスを一旦削除します。その入力欄に「cmd」と入力してEnterキーを押下すると、そのディレクトリでコマンドプロンプトの操作が行えます。都度対象のフォルダにチェンジディレクトリしてから～という過程を経なくても良くなり、便利であるためぜひ覚えておいてください。
 
![codespaces_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/745966af-d458-7a5b-dd49-6db685dbf1c9.gif)

まずtestフォルダを作成します
```
mkdir test
```

testフォルダが作成できたら、testフォルダにチェンジディレクトリします。
```
cd test
```

testフォルダがカレントディレクトリとなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/c5ef5466-e817-c1f3-dbd5-740d54e71ee7.png)

testの中にリポジトリを作成するため、下記のコマンドを実行します。（=>より右側は実行結果です。）

```
git init

=>Initialized empty Git repository in C:/Users/USER/Desktop/git_practice/test/.git/
```

空のリポジトリを作成することができ、リポジトリの初期化の作業は完了です。

## 差分確認
では、新しいファイルを作成してみましょう。
windowsのコマンドもしくはVSCodeを使用してtestディレクトリに下記の内容のファイルを作成します。

```test1.js
console.log('test');
```

このファイルの作成ができたら、ターミナルを開いて下記のコマンドを実行します。
```
git status

->
PS C:\Users\USER\Desktop\git_practice\test> git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test1.js

nothing added to commit but untracked files present (use "git add" to track) 
```
上記のように結果が表示されます。「git status」コマンドを使用することで、現在自分がいるブランチの状態を確認することができます。「No commits yet」は、コミットがまだ行われていないという意味です。Untracked filesはファイルが作成されたばかりで、まだgit add コマンドでステージングされていないという意味です。

git commitと git addは下記にて説明します。

## 開発フロー
gitにおける開発フローについてざっくりですが説明していきます。
開発フロー全体、というと厳密に異なるかもしれませんが、
**「コミット」** というプロセスを経て、**「リモートリポジトリにプッシュする」** という流れについて説明していきます。

----------------------------------
**コミット**
…ファイルの変更履歴を保存する操作のことです。
変更履歴を保存しておけば、誰がどのディレクトリのどのファイルをどのように修正したかがわかるようになります。

このコミットの流れを先に説明しておきます。

**①差分確認**
まず修正したファイルの内容があっているかどうか、差分として表示されているのが自分の修正のみとなっているかを確認します。
```
git diff --color
```
**--color**
Gitの差分表示を色付きで行うためのオプションです。これにより、変更箇所が視覚的にわかりやすくなります。

**②：ステージング**
…変更したファイルをステージングエリアに追加します。
```bash
# 1ファイルのみ指定してステージングする場合
git add ファイル名

# 変更したすべてのファイルをステージングする場合（「.」はドットです。）
git add .
```

**③：コミット**
…ステージングエリアに追加された変更をコミットします。
コミットにはメッセージを付けることができ、どんな機能のどんな修正をおこなったかを記述し、自分や他の開発者に共有することができます。基本的にコミットコメントは記述することが推奨されます。


（例１）git commitと記述して、テキストエディタを開いてコミットコメントを記述する方法
「git commit」　⇒　「iキー」インサートモード　⇒　コメント入力　⇒　「Esc」キー　⇒「:wq」を入力

```
git commit
```

（例２）git comment -m と記述してテキストエディタを開かずにコミットコメントを記述する方法

```
git commit -m "〇〇ファイルを更新しました"
```

**【※ 要注意事項】**
**git add でステージングをしていないものはコミットできません。コミットする場合は必ずgit add を行って、対象ファイルをステージングしてください。**


**④：コミットの修正**
…間違った変更をコミットしてしまった場合、直前のコミットを修正したり、それ以前の過去のコミットを修正することができます。

　**直前のコミットを修正するコマンド**
```
git commit --amend -m "修正後のコミットメッセージ"
```
-----------------

　**過去のコミットを修正する方法**

修正したいコミットの確認をします。（このコマンドでコミットの履歴が羅列されます）
```
git log
```

下記コマンドで、修正したいコミットの１つ前のコミットハッシュを指定します。
```
git rebase -i [コミットハッシュ]
```

リベースモードに入るので、修正したいコミットのpickをeditに変更して保存します。

下記のコマンドを使用して修正を行います。
```
git commit --amend
```

修正が完了したら下記のコマンドでリベースモードを終了します。

```
git rebase --continue
```


**⑤：コミットの確認**
修正の要不要にかかわらず、プッシュする前は必ずコミットの確認をすることを推奨します。

```
git log
```


**(⑥：リモートリポジトリへのプッシュ)**
適用したい変更がコミットされていることが確認出来たら、下記のコマンドでコミットをリモートリポジトリへプッシュします。
**※現在の状態だと、まだリモートにリポジトリを作成していない状態であるためGitHubを連携させてからリモートリポジトリへのプッシュを行うことができます。**

```
git push origin [適用先のブランチ名]
```

この流れで、ローカルリポジトリの変更をリモートリポジトリに反映することができます。

## ブランチの作成と移動
現在mainブランチしか作成していませんが、今後複数人で開発を行ったり、場面ごとに開発を行ったりするのに合わせてmainブランチを枝分かれさせて、いわゆるmainの内容と同一のコピーを作成してみましょう。

```
 git checkout -b branch_a
 
 
 ->Switched to a new branch 'branch_a'
```
このコマンドでmainブランチが枝分かれし、branch_aというブランチが作成されます。
（この時点のbranch_aの内容はmainブランチと同一です。）


現在のブランチの状態を確認してみましょう。
```
git status

-> On branch branch_a
```

mainブランチから「branch_a」に切り替わっています。これでブランチの作成は完了です。
mainという大元のソースコードを保持しておきながら、branch_aで修正作業を行うことができます。

ちなみにmainブランチへ再び戻るには下記コマンドでmainブランチに戻ることができます。

```
 git checkout main

-> Switched to branch 'main'
```

## マージ
**マージ**
…複数のものを１つにまとめるという意味を持ちます。Gitでは異なるブランチの変更を１つに統合するための操作のことを言います。この作業により複数人の開発者が並行して作業した内容を１つのブランチにまとめることができます。

この図を確認してください。mainブランチから始まり、例えば部分的な修正のために
「branch_a」「branch_b」というブランチを枝分かれさせて作成します。
「branch_a」「branch_b」ブランチで修正を行い、その内容をmainブランチにマージするという流れになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/a105aef8-710a-9179-28ca-6a6bbbc48bf7.png)
（「branch_a」がmainにマージされている図です）

ではbranch_aの内容(test1.js)を変更し、mainブランチにbranch_aをマージしてみましょう

```test1.js
console.log('test_a');
```

この内容で保存し、git add とgit commitを行います。

```
git add .
```

```
git commit -m 'test_aに変更'
```

git logでコミットが行えたか確認する。
```
git log
```

次にブランチをmainに切り替えます。

```
git checkout main
```
下記のようにコマンドを入力し、実行します。意味合いは(mainブランチに)branch_aをマージするという意味になります。
```
git merge branch_a

->Updating dc702cb..e8c2278
Fast-forward
 test1.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
```

これでmainブランチのtest1.jsの内容が更新できました。branch_aの更新内容がmainブランチにも反映されています。
```test1.js
console.log('test_a');
```


## 競合（コンフリクト）
Gitを複数人で扱う上で避けられないのが修正箇所の**競合**です。

**競合**
…複数の開発者が同じファイルの同じ部分を変更した場合に発生します。
Git側でどの変更を適用するべきかが判断できないため、競合は**手動**で解決する必要があります。

図で表すと以下のようになります。mainブランチにマージしようと思っていたbranch_aとbranch_bの修正箇所が重複していた場合に競合が発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/765c6f25-45b1-e460-92d7-3e4d163b7638.png)

この競合を解決する手順は下記のようになります。

まず競合を発生させるために、branch_aに移動し、再度変更して保存します。

```
git checkout branch_a
```

```javascript:test1.js
console.log('test_a_2');
```


git add⇒git commitします。

```
git add.
```

```
git commit -m 'branch_aの修正'
```

次にmainブランチに移動し、branch_bを作成して、変更して保存します。

```
git checkout main
```

```
git checkout -b branch_b
```

これでbranch_bを作成・branch_bに移動することができたので変更内容は下記のようにして保存します。
```
console.log('test_b_2');
```

branch_aと同様にgit add とgit commitをします。

```
git add .
```

```
git commit -m 'branch_bの修正'
```

ここまで作業が完了したら、mainブランチに切り替え、branch_aとbranch_bのマージを行います。

```
git checkout main
```

branch_aのマージはうまくいきますが…
```
 git merge branch_a

->
Updating e8c2278..c27801f
Fast-forward
 test1.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
```
branch_bのマージはうまくいきません。競合が発生しているからです。
```
 git merge branch_b

->
Auto-merging test1.js
CONFLICT (content): Merge conflict in test1.js
Automatic merge failed; fix conflicts and then commit the result.
```

VSCodeを確認してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/13541dfe-680d-1b17-b21f-8fe162ac6a9b.png)
このように現在（branch_a）の変更とbranch_bで変更しようとしているところが競合しているため、下記のようにコードが表示されます。

今回はbranch_bの修正を反映するため、「（入力側の変更）」となっている青色の修正箇所を残します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906686/e9e226c1-e7fc-630a-b8ed-e12bfd601f47.png)

競合が解消できたら、git add とgit commitします。

```
git add .
```

```
git commit -m '競合を解決しました。'
```

下記のコマンドでコミットの流れが確認できます。
```
git log
```