Gitのリモートリポジトリとローカルリポジトリでの奮闘記

# 背景・目的
メンバーと編集しているファイルでコンフリクトが多発。
Git初心者がコンフリクトを回避できるように 、ローカルリポジトリとリモートリポジトリの違いを理解することを目的とする。

# Gitのプルとマージの関係について

Gitを使って開発する際、最新のソースコードを取得する場面は多分にあると思います。しかし、プルやマージの仕組みや違いを理解していないと、コンフリクトやエラーに悩まされることになります。そこで今回は、Gitのプルとマージの関係について、先生と生徒の会話形式で解説していきます。

## 生徒: プルしたとき、ローカルリポジトリのブランチにもマージされてしまうのでしょうか？

先生:答えは、はい、されてしまいます。git pullコマンドは、リモートリポジトリから最新の状態をローカルリポジトリに反映するコマンドですが、その際に git fetch と git merge の二つの操作を行っています。

git fetch は、リモートリポジトリのブランチやコミットの情報をローカルに取得するだけで、ローカルのブランチには影響しません。しかし git merge は、取得した情報をローカルのブランチに統合する操作で、ローカルのブランチに変更を加えます。

つまり、git pull は git fetch + git merge ということになります。そのため、プルしたときにローカルリポジトリのブランチにもマージされてしまうのです。

もしプルしたときにマージされないようにしたい場合は、git pull の代わりに git fetch を使ってください。git fetch だけではローカルのブランチは更新されないので、マージするタイミングを自分で決めることができます。

## 生徒: ローカルで編集したコードをpushする前にfetchかプルをする必要があるのでしょうか？その場合、マージされてしまって、せっかく編集したコードがなくなってしまいませんか？

先生: ローカルで編集したコードをpushする前にfetchかプルをする必要があるかどうかは、リモートリポジトリの状態によります。もしリモートリポジトリに他の人がpushしていたり、ブランチが更新されていたりする場合は、fetchかプルをする必要があります。そうしないと、pushするときにコンフリクトが発生する可能性が高くなります 。

fetchかプルをするときに、ローカルで編集したコードがなくなってしまうことはありません。fetchの場合は、ローカルのブランチには影響を与えないので、安心して実行できます 。プルの場合は、ローカルのブランチにマージされるので、コードが変更される可能性がありますが、ローカルで編集したコードは消えることはありません 。もしマージするときにコンフリクトが発生した場合は、自分で解決する必要があります。

コンフリクトを解決する方法は、コンフリクトが発生したファイルを開いて、自分の意図した内容に修正することです。コンフリクトが発生したファイルには、以下のようなマークが表示されます。

```
<<<<<<< HEAD
ローカルで編集した内容
=======
リモートで編集した内容
>>>>>>>
```


このマークは、ローカルとリモートで異なる内容に変更された箇所を示しています。HEADはローカルのブランチを、=======の下はリモートのブランチを表しています。このマークを削除して、自分の意図した内容に修正します。例えば、ローカルで編集した内容を採用する場合は、以下のようにします。


```
ローカルで編集した内容
```


修正したら、git addコマンドとgit commitコマンドでコンフリクトを解消したことを記録します。その後、git pushコマンドでリモートに反映します。

もう少し具体的に説明します。
もしローカルで編集した内容を採用する場合は、以下の手順で行います。

1. コンフリクトが発生したファイルを開きます。
2. マークの間にあるリモートで編集した内容を削除します。
3. マーク自体も削除します。
4. ファイルを保存します。

例えば、以下のようなファイルがコンフリクトしていたとします。

```
Gitの使い方
Gitは分散型バージョン管理システムです。
<<<<<<< HEAD Gitはオープンソースで無料で利用できます。
GitはLinuxカーネルの開発に使われています。
```

この場合、ローカルで編集した内容を採用すると、以下のようになります。

```
Gitの使い方
Gitは分散型バージョン管理システムです。
Gitはオープンソースで無料で利用できます。
```

修正したら、git addコマンドとgit commitコマンドでコンフリクトを解消したことを記録します。その後、git pushコマンドでリモートに反映します。


## 生徒: 他の誰かがリモートリポジトリを編集していて、自分がローカルリポジトリを編集していた場合、コンフリクトを防ぐ方法を教えてください

先生:コンフリクトとは、同じファイルの同じ箇所を異なる内容で変更したときに発生する問題です。コンフリクトを防ぐ方法はいくつかありますが、代表的なものは以下の通りです。

- ブランチを使う : ブランチとは、コミット履歴の分岐点です。ブランチを使うと、自分の作業を他の人と分離して行うことができます。例えば、masterブランチからfeatureブランチを作って、新しい機能を開発するというようにします。ブランチを使うことで、同じファイルを同時に編集する可能性が低くなります。また、ブランチをマージするときにコンフリクトが発生した場合は、自分で解決する必要がありますが、その範囲が限定されるので、対処しやすくなります。
- 定期的にプルする : プルとは、リモートリポジトリから最新の状態をローカルリポジトリに反映する操作です。プルすることで、他の人がリモートリポジトリに加えた変更を自分のローカルリポジトリに取り込むことができます。定期的にプルすることで、自分のローカルリポジトリを常に最新の状態に保つことができます。その結果、他の人との差分が少なくなり、コンフリクトが発生しにくくなります。
- コミットやプッシュを小さく分ける : コミットとは、ローカルリポジトリに変更内容を保存する操作です。プッシュとは、ローカルリポジトリからリモートリポジトリに変更内容を送信する操作です。コミットやプッシュを小さく分けることで、変更内容を細かく管理することができます。例えば、一つの機能を実装するために複数のファイルを変更した場合でも、一つずつコミットしてプッシュするというようにします。コミットやプッシュを小さく分けることで、他の人との同期を頻繁に行うことができます。その結果、他の人との差分が少なくなり、コンフリクトが発生しにくくなります。

以上が、他の誰かがリモートリポジトリを編集していて、自分がローカルリポジトリを編集していた場合、コンフリクトを防ぐ方法です。コンフリクトは完全に防ぐことはできませんが、上記の方法を実践することで、発生率や影響度を低減することができます。

## 生徒: ブランチを使う場合、作成されたものは、リモートリポジトリのブランチ作成ではないでしょうか？

先生: いいえ、リモートリポジトリのブランチの作成とは異なります。リモートリポジトリのブランチとは、オンライン上にあるリポジトリのブランチです。ローカルリポジトリのブランチとは、自分のコンピュータ上にあるリポジトリのブランチです。ローカルリポジトリでブランチを作成すると、そのブランチは自分のコンピュータ内にしか存在しません。リモートリポジトリにそのブランチを反映するには、pushする必要があります。

例えば、ローカルのmasterブランチからfeatureブランチを作成したとします。このとき、featureブランチはローカルにしか存在しません。もし他の人にもそのブランチを見てもらいたい場合は、以下のようにしてリモートリポジトリにpushします。

```
git push origin feature
```


これで、リモートリポジトリにもfeatureブランチが作成されます。このとき、ローカルのfeatureブランチとリモートのfeatureブランチは同じ内容になりますが、別々のブランチであることに注意してください。ローカルでfeatureブランチを変更した場合は、再びpushする必要があります。

## 生徒: ローカルのブランチとリモートのブランチを同期する方法を教えてください。

先生:ローカルのブランチとリモートのブランチを同期するには、以下の二つの操作が必要です。

- リモートのブランチの変更をローカルに反映する : これは、git pullコマンドかgit fetchコマンドを使って行います。git pullコマンドは、リモートのブランチの変更をローカルに取得して、自動的にローカルのブランチにマージします。git fetchコマンドは、リモートのブランチの変更をローカルに取得するだけで、ローカルのブランチには反映しません。そのため、git fetchした後には、git mergeかgit rebaseを使って、ローカルのブランチに手動で反映する必要があります。
- ローカルのブランチの変更をリモートに反映する : これは、git pushコマンドを使って行います。git pushコマンドは、ローカルのブランチの変更をリモートに送信して、リモートのブランチに反映します。

以上が、ローカルのブランチとリモートのブランチを同期する方法です。ただし、同期するときには注意が必要です。同期する前に、他の人がリモートのブランチに変更を加えていないか確認することが重要です。もし他の人が変更を加えていた場合は、コンフリクトが発生する可能性があります。その場合は、自分で解決する必要があります。

# おわりに

いかがでしたでしょうか？
Gitは難しく感じることもあるかもしれませんが、基本的な仕組みや操作を理解すれば、開発効率や品質を向上させることができます。
ぜひこの記事を参考にして、Gitを使いこなしてみてください。