こんにちは。野中やすおです。
今回の記事では、いつもgitを使用する際に迷ってしまうgit fetch、git pull、git mergeの違いについて自分のメモがてら記事にしています。
前提知識
- 「main」ブランチ…ローカル上の統合ブランチで、他ローカルの作業ブランチと繋がっているブランチのこと。
- 「origin/main」ブランチ…ローカル上のリモートmainブランチを追跡するリモート追跡ブランチのこと。
前提知識として上記のブランチの違いを理解することが本記事を理解する上で重要となります。
git fetch
git fetchコマンドは、リモートリポジトリから最新の情報をローカルリポジトリに取得するために使用されます。
言い換えれば、git fetchはローカルの作業を変更せず、リモートリポジトリの状態を単に「取得する」ためだけに使われます。そして取り込まれる場所は、「main」ブランチではなく、「origin/main」ブランチになります。
git fetchの具体例
自分が「main」ブランチから「feature/xxxx」ブランチで作業をしているとします。作業中、同僚がリモートの「origin/main」ブランチに新しい変更をプッシュしました。なので、一旦mainブランチを最新の状態に保ちたいと思い、git fetchを行います。
mainブランチの変更を取得したい場合は、
1 |
git checkout main |
とした上で、
1 |
git fetch |
とします。
上記の結果、ローカルの「origin/main」ブランチに対し、リモートのmainブランチの最新状態が反映されます。変更がローカルのリポジトリに取り込まれますが、自分の手元にある「main」ブランチのコードはそのまま残ります。またgit fetchは、現在の作業ブランチ(「feature/xxxx」)にも影響を与えません。
またgit fetchにはオプションもあります。私はほとんど使ったことがありませんが、公式でオプションの引数が紹介されているのでこちらも参考になります。
git merge
git mergeコマンドは、別ブランチの変更を現在のブランチに統合するために使用されます。
git mergeの具体例
作業していた「feature/xxxx」ブランチで開発が完了し、レビューも完了しました。その後、これを「main」ブランチに統合したいとします。
1 |
git checkout main |
で「main」ブランチに切り替えた後、
1 |
git merge feature/xxx |
を実行することで、「feature/xxx」ブランチの変更が「main」ブランチに統合されます。とはいえ、実際にコマンドを使用して、mainに対してマージを行う現場はかなり少ないかなと思います。よくgit megeを使用する例としては、最新の「main」ブランチの状態を作業ブランチに反映したい場合などに使用されます。
git merge origin mainを使用する場合
まずは例として、git merge origin mainコマンドを使用する場合です。
「origin/main」ブランチにリモートのmainブランチの最新情報が反映された状態で、
1 |
git checkout feature/xxx |
として、
1 |
git merge origin main |
とすると、「main」ブランチにおける最新コミットを「feature/xxx」にマージすることができます。
git merge mainを使用する場合
一方で、git merge mainコマンドは、ローカルリポジトリにある「main」ブランチの最新コミット(ローカルの main ブランチが最新の状態を前提として)を「feature/xxx」にマージします。 mainはあくまでローカルリポジトリのブランチなので、リモートリポジトリの状態には依存しません。
git merge origin mainとgit merge mainの使い分けについて
あえて使い分けるのであれば、リモートの main ブランチが最新の情報源である場合、git merge origin main を使用し、ローカルの「main」ブランチが最新である場合かつ安全性を重視するのであれば、git merge mainを使用すると良いと思います。
ただし、私自身は、最新の内容を取り込む際にはgit merge origin mainを使用していて、git merge mainは使用していないですねー。
git pull
git pullコマンドは、上記で紹介した「git fetch + git merge」を同時に実行するコマンドで、リモートリポジトリの変更を現在のローカルブランチに統合します。
つまり、リモートの「main」ブランチから、ローカルの「origin/main」ブランチを通じて、ローカルの「main」まで一気に最新情報を持ってきます。
なので、git pullを使用するとローカルでコンフリクトが発生しやすことには注意が必要です。
ということもあってまずはgit fetchで様子見をして、その後、改めてgit pullでローカルにマージをするという運用が無難かなと思います(私は経験2年目くらいからそうしています)。
もしコンフリクトが発生してしまった場合に
git pullを実行したことでコンフリクトが発生した場合の手順は以下になります。
まずは、mergeした分を破棄するために
1 |
git merge --abort |
とします。
そしてgit fetchを取り消すために
1 |
git reset --hard HEAD^ |
として(直前の)コミットを取り消します。
ちなみにgit fetchを実行時にコンフリクトが発生した場合は、まだマージはしていないので、
1 |
git reset --hard HEAD^ |
だけで済みます。
git pullの具体例
引き続き「feature/xxx」ブランチで作業しているとします。git pullを実行すると、まずgit fetchが行われるので、
1 |
git checkout main |
でローカルの「main」ブランチに移動した後、
1 |
git pull |
を実行します。そうすることで「origin/main」の最新変更が取得され、ローカルの「main」ブランチにマージされます。
最後に
以上、git fetch、git pull、git mergeの違いを紹介してきました。
そして習慣的になんとなくやっていたまずはgit fetchで様子見をして、その後、改めてgit pullでローカルにマージするというのも今回の記事にまとめることで腑におちました。
参考
- git fetchについて
- git mergeについて
- git pullについて