git fetch(フェッチ)とは何か?使い方を実例で解説|引数が無い場合の処理やブランチ名の指定、サブモジュールがあるときの挙動

github-prograshi(プロぐらし)-kv git/github
記事内に広告が含まれていることがあります。

Githubを使ったプロジェクトで頻繁に使用するコマンドの一つにgit fetch(フェッチ)があります。

Githubのリモートレポジトリの情報をとってくるんでしょ?という理解をされている方は多いと思います。

ですが、git fetchは実はできることがたくさんあるとても便利なコマンドです。ただし、使い方には癖があり、理解が必要です。

ここではgit fetchでできることについて実例を踏まえてまとめています。


git fetchとは何か?

git fetch(フェッチ)はリモートレポジトリのコミット履歴をとってきて、ローカルレポジトリにコピーするコマンドです。

ローカルレポジトリのリモート追跡ブランチのコミット履歴をアップデートするだけで、マージは行いません。

なお、「fetch」は取ってくると言う意味です。


リモート追跡ブランチとは何か?

Gitではローカルレポジトリのブランチとリモートレポジトリの同じ名前のブランチが直接連携しているわけではありません

このため、例えば、ローカルレポジトリのmainブランチで作業しているときに、git fetchを行うと、コミット履歴が更新されるのはローカルレポジトリのmainブランチではありません。

リモートレポジトリの各ブランチと直接連動しているブランチは他にあり、そのブランチのことを「リモート追跡ブランチ」と呼びます。

リモート追跡ブランチは「remotes/リモートレポジトリ名/リモートブランチ名」という名前がついているブランチです。(例: remotes/origin/main)

リモート追跡ブランチは「git branch -a」で参照できます。-aはall(全てのブランチ)という意味です。


実例:リモート追跡ブランチの参照

$ git branch -a
* aa
  main
  vue-router
  remotes/origin/HEAD -> origin/main
  remotes/origin/aa
  remotes/origin/main

上記の例だと、リモートレポジトリには「main」と「aa」の2つのブランチがあり、それぞれのリモート追跡ブランチは「remotes/origin/main」「remotes/origin/aa」となっていることがわかります。

なお、「remotes/origin/HEAD -> origin/main」は取得してきた時点で最新のリモートレポジトリのデフォルトブランチを指しています。

「remotes/origin/HEAD」を使うことはほぼないので、あまり気にする必要はありません。

「remotes/origin/ブランチ名」はよく使うので覚えておく必要があります。


git fetchの使いどころやメリット

他のプロジェクトメンバーが作業進めたかな?メインのブランチ(mainやmasterなど)でアップデートがあったかな?といったことを調べたいときに使います。

git fetchした後は、ローカルレポジトリのコミット履歴がアップデートされるので、必要に応じてgit mergeやgit rebaseを実行してコミットを取り込むことができます。

強制的にマージまで実行してしまうgit pullと違って、自分でマージのタイミングを選べるのもgit fetchのポイントです。

リモートレポジトリのブランチの状態をそのまま再現できる。


git fetchの使い方

git fetchは主に次の5つの使い方があります。

git fetchの主な使い方
  1. 【引数なし】git fetch
  2. 【レポジトリ名を指定】 指定したリモートレポジトリの全てのブランチの最新のコミット履歴をとってくる。
  3. 【レポジトリ名とブランチ名を指定】 指定したリモートレポジトリのブランチの最新のコミット履歴のみをとってくる。
  4. 【レポジトリ名とブランチ名と、生成するブランチ名を指定】指定したリモートレポジトリのブランチの最新のコミット履歴のみをとってきて、新たなブランチを作る。
  5. --allオプション】全てのリモートレポジトリの全てのブランチの最新のコミット履歴をとってくる。


それぞれのコマンドは以下のようになります。

コマンドコマンド例内容
git fetch(引数無し)git fetch取得対象のリモートレポジトリの優先度: 「上流ブランチ」 > 「origin」 
git fetch <リモートレポジトリ名>git fetch second指定したリモートレポジトリの最新のコミット履歴をまるごと取得
git fetch <リモートレポジトリ名> <ブランチ名>git fetch origin main指定したリモートレポジトリの指定したブランチのみの最新のコミット履歴を取得
git fetch <リモートレポジトリ名> <ブランチ名>:<生成するブランチ名>git fetch origin main:test指定したリモートレポジトリの指定したブランチのみの最新のコミット履歴を取得して、新たなローカルブランチを作成
git fetch --allgit fetch --all全てのリモートレポジトリの全てのブランチの最新のコミット履歴をとってくる


引数なしのgit fetch

引数なしのgit fetchの使い方

git fetchを引数なしで実行した場合は、実行したブランチに上流ブランチが設定してある場合は、上流ブランチの最新のコミット履歴を取得してきます。

上流ブランチが設定されておらず、リモートレポジトリ名に「origin」が登録されている場合は、「origin」というリモートレポジトリのすべてのブランチの最新のコミットをまるごととってきます。

git fetch

上流ブランチとは、ローカルレポジトリのブランチ毎に設定するもので、ローカルブランチをリモートレポジトリのブランチと紐づけるものです。

上流ブランチを設定すると、git pushなどのコマンドの引数を省略することができます。

合わせて読みたい

上流ブランチの設定方法や詳しい実例を知りたい方は下記をご参考ください。

【Github】git pushの-uオプションとは何か?upstreamや上流ブランチについて実例で解説


実例

まずはローカルレポジトリに登録してあるリモートレポジトリ名確認します。上流ブランチの有無も含めて確認する場合は git remote -vvを実行します。

$ git remote -vv
origin  https://github.com/xxxx/rails-test.git (fetch)
origin  https://github.com/xxxx/rails-test.git (push)

上流ブランチはなしでリモートレポジトリ「origin」があります。このためgit fetchを実行すると「origin」の全てのブランチの最新のコミット履歴をとってくる処理になります。

git fetch

remote: Enumerating objects: 89, done.
remote: Counting objects: 100% (89/89), done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 89 (delta 46), reused 80 (delta 38), pack-reused 0
Unpacking objects: 100% (89/89), done.
From github.com:xxx/git-test
   8fccfd033..2a06b79c8  hotfix           -> origin/hotfix
   6115dc29d..1f60a6761  develop          -> origin/develop
 * [new branch]      ft1        -> origin/ft1
 * [new branch]      test       -> origin/test

大きく2つの記述があることがわかります。(なお更新内容が無い場合は上記のような表示はありません)


既存のリモート追跡ブランチのコミット履歴を更新

1つ目はコミット番号とブランチ名が表示されているものです。

8fccfd033..2a06b79c8  hotfix           -> origin/hotfix

これは以下のような記述になります。

<更新していない最初のコミット番号>..<最新のコミット番号>  <リモートレポジトリのブランチ名>           -> <リモート追跡ブランチ名>

つまり、既にリモート追跡ブランチとして存在している「hotfix」ブランチにコミット番号「8fccfd033」から「2a06b79c8」までが追加されたという内容です。


新たなリモート追跡ブランチを作成

2つ目は[new branch]と記載があるものです。

* [new branch]      ft1        -> origin/ft1

これは以下のような記述になります。

* [new branch]     <リモートレポジトリのブランチ名>           -> <リモート追跡ブランチ名>

つまり、リモートレポジトリに新たに「ft1」というブランチが追加されているので、「origin/ft1」というリモート追跡ブランチを新たに生成しましたという意味です。


git fetchで上流ブランチを設定する方法

git fetchで上流ブランチを設定するには、通常のgit fetch <リモートレポジトリ名> <リモートのブランチ名>に「--set-upstream」オプションを付けて実行します。

git fetch --set-upstream <リモートレポジトリ名> <リモートのブランチ名>

なお、upstreamは上流という意味です。

初回の実行で上流ブランチをセットすれば、後は引数無しのgit fetchコマンドが使えます。

注意点
  • 上流ブランチを設定するための初回のgit fetchでは引数を省略することはできません。
  • git pushと違いショートオプション「-u」は存在しません。


リモートレポジトリ名を指定したgit fetch

リモートレポジトリ名を指定したgit fetchの使い方

リモートレポジトリが複数登録してある場合など、対象のリモートレポジトリを指定してgit fetchすることもできます。

その場合は第2引数でリモートレポジトリ名を指定します。

git fetch <リモートレポジトリ名>


実例

まずはローカルレポジトリに登録してあるリモートレポジトリ名確認します。

$ git remote -v
origin  https://github.com/xxxx/rails-test.git (fetch)
origin  https://github.com/xxxx/rails-test.git (push)
second  https://github.com/yyyy/git-test.git (fetch)
second  https://github.com/yyyy/git-test.git (push)

「origin」と「second」という名前のリモートレポジトリが2つ登録されていることがわかります。

git fetchで「second」のリモートレポジトリの全てのブランチの最新のコミット履歴をとってきます。

git fetch second

remote: Enumerating objects: 89, done.
remote: Counting objects: 100% (89/89), done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 89 (delta 46), reused 80 (delta 38), pack-reused 0
Unpacking objects: 100% (89/89), done.
From github.com:yyyy/git-test
 * [new branch]      aa         -> second/aa
 * [new branch]      main       -> second/main

上記の場合は、git fetchの結果、新しいリモート追跡ブランチ「second/aa」と「second/main」が追加されたことがわかります。

実際にブランチを確認すると以下のようにリモート追跡ブランチが生成されているのがわかります。

$ git branch -a
* aa
  main
  vue-router
  remotes/origin/HEAD -> origin/main
  remotes/origin/aa
  remotes/origin/main
  remotes/second/aa
  remotes/second/main


リモートレポジトリが存在しない場合はエラーになる

指定したリモートレポジトリが存在しない場合は「fatal: ‘リモートレポジトリ名’ does not appear to be a git repository」「fatal: Could not read from remote repository.」というエラーが表示されます。

$ git fetch no
fatal: 'no' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.


リモートレポジトリ名とブランチ名を指定してgit fetchする

リモートレポジトリ名とブランチ名を指定したgit fetchの使い方

「全てのブランチの情報ではなく、特定のブランチの更新履歴だけが欲しい」という場合は、リモートレポジトリのブランチ名を指定することもできます。

git fetch <リモートレポジトリ名> <リモートレポジトリのブランチ名>


実例

まずはローカルレポジトリに登録してあるリモート追跡ブランチを確認します。

$ git branch -a
* aa
  main
  vue-router
  remotes/origin/HEAD -> origin/main
  remotes/origin/aa
  remotes/origin/main
  remotes/second/aa
  remotes/second/main

この中で、リモート追跡ブランチ「remotes/origin/main」すなわちリモートレポジトリ名「origin」ブランチ名「main」のみを更新したい場合は、git fetchの第1引数に「origin」、第2引数に「main」を指定します。

$ git fetch origin main
From https://github.com/xxxxx/rails-test
 * branch            main       -> FETCH_HEAD

上記のように表示され、指定したリモート追跡ブランチの情報のみが更新されていることがわかります。


ブランチが存在しない場合はエラーになる

指定したブランチが存在しない場合は「fatal: couldn’t find remote ref ブランチ名」というエラーが表示されます。

$ git fetch second no
fatal: couldn't find remote ref no



リモートレポジトリ名とブランチ名と、生成するブランチ名を指定してgit fetchする

リモートレポジトリ名とブランチ名と、生成するブランチ名を指定したgit fetchの使い方

リモートレポジトリ名とブランチ名と、生成するブランチ名を指定してgit fetchすると、指定したリモートレポジトリのブランチの内容で、新たなブランチをローカルに生成することができます。

git fetch <リモートレポジトリ名> <リモートのブランチ名>:<ローカルに生成するブランチ名>

なお、ローカルに指定したリモートの追跡ブランチが存在する場合は、指定したローカルブランチのみを生成します。

どちらもない場合は、(1)追跡ブランチと(2)指定したローカルブランチの2つを作成します。


実例

リモートレポジトリ名「origin」のブランチ「master」を、ローカルレポジトリに「test」というブランチ名として生成する場合は以下のようになります。

$ git fetch origin master:test

remote: Enumerating objects: 70, done.
remote: Counting objects: 100% (70/70), done.
remote: Compressing objects: 100% (31/31), done.
remote: Total 70 (delta 41), reused 62 (delta 34), pack-reused 0
Unpacking objects: 100% (70/70), done.
From github.com:xxxx/rails-test
 * [new branch]      master     -> test
 * [new branch]      master     -> origin/master

新たにローカルブランチ「test」と、リモートブランチ「origin/master」が生成されたことがわかります。

ブランチの状態を確認すると、それぞれのブランチが生成されていることがわかります。

$ git branch -a
  test
  remotes/origin/master


全てのリモートレポジトリの全てのブランチの情報をとってくるオプション(--all)

--allオプションの使い方

引数無しのgit fetchを実行した場合、上流ブランチがある場合や、リモートレポジトリ名「origin」がある場合といった制約がつきます。

細かいことは抜きにして登録してある全てのリモートレポジトリの全てのブランチの最新のコミットを取ってきたい場合は「--all」オプションを使用します。

git fetch --all


実例

ローカルレポジトリに登録してあるリモートレポジトリ名が以下のような状態だとします。

$ git remote -v
origin  https://github.com/xxxx/rails-test.git (fetch)
origin  https://github.com/xxxx/rails-test.git (push)
second  https://github.com/yyyy/git-test.git (fetch)
second  https://github.com/yyyy/git-test.git (push)

登録してあるリモートレポジトリは「origin」と「second」の2つです。この状態で–allオプションをつけたgit fetchを実行すると次のようになります。

$ git fetch --all
Fetching origin
Fetching second

このように、「origin」と「second」の両方とものリモートレポジトリをfetchしていることがわかります。



サブモジュールがある場合のgit fetch

サブモジュールがある場合のgit fetchの処理内容

リモートレポジトリにサブモジュールが存在するときに「git fetch」を実行すると、メインのリモートレポジトリの内容だけでなく、サブモジュールの内容も取得することができます。


実例

$ git fetch
remote: Enumerating objects: 193, done.
remote: Counting objects: 100% (193/193), done.
remote: Compressing objects: 100% (79/79), done.
remote: Total 193 (delta 135), reused 156 (delta 114), pack-reused 0
Receiving objects: 100% (193/193), 82.78 KiB | 657.00 KiB/s, done.
Resolving deltas: 100% (135/135), completed with 48 local objects.
From github.com:xxxx/rails-pj
   8fccfd033..2a06b79c8  test            -> origin/test
 * [new branch]          apc              -> origin/apc
   888570c19..0ce7f2188  master           -> origin/master
 + 98ab8117f...c3d2ff203 test_ga            -> origin/test_ga  (forced update)
Fetching submodule rails-user
From github.com:xxxx/rails-user
   f5bd9fa..e0af519  master     -> origin/master
   6439adb..e63c502  test      -> origin/test
Fetching submodule rails-api
From github.com:xxxx/rails-api
   d2ab8a8..865f236  master          -> origin/master
 + 302d6ae...8aa0c0e ft              -> origin/ft  (forced update)
 * [new branch]      pr              -> origin/pr

上記の場合、実行したのはgit fetchのみですが、メインのリモートレポジトリ「rails-pj」以外に、サブモジュール「rails-user」と「rails-api」の全てのブランチの最新のコミットも取得していることがわかります。


git fetchした内容をマージやリベースする方法

git fetchをした後に、取得してきた内容を作業中のローカルレポジトリのブランチにマージすることが頻繁に発生します。

その場合は更新されたリモート追跡ブランチをマージ、あるいはリベース対象として指定します。


git mergeする方法

git mergeで現在作業中のブランチに、コミットを取得してきたリモート追跡ブランチの内容を取り込みたい場合は以下のようにします。

git merge remote/<リモートレポジトリ名>/<リモートのブランチ名>
point

リモート追跡ブランチを指定するときは、冒頭の「remote/」を省略することができます。

git merge origin/main

 ↑↓ 同じ

git merge remotes/origin/main


実例

例えば、以下のようなブランチの状態だとします。

$ git branch -a
  aa
  main
* test
  remotes/origin/HEAD -> origin/main
  remotes/origin/aa
  remotes/origin/main

このときに、現在のtestブランチにおいて、リモート追跡ブランチ「remotes/origin/aa」の内容をマージで取り込みたい場合は以下のようにします。

$ git merge origin/aa
Updating a90d4ef..0701d9d
Fast-forward
 docker-compose.yml | 2 ++
 1 file changed, 2 insertions(+)

すると、git fetchしてきた最新のリモートレポジトリ「origin」の「aa」ブランチの情報をマージすることができます。

合わせて読みたい

git mergeの処理内容や詳細、コンフリクトが発生した場合の対処法については下記をご参考ください。

【Git】git merge(マージ)とは何か?使い方を実例で解説

git rebaseする方法

git rebaseで現在作業中のブランチに、コミットを取得してきたリモート追跡ブランチの内容を取り込みたい場合は以下のようにします。

git rebase remote/<リモートレポジトリ名>/<リモートのブランチ名>
point

リモート追跡ブランチを指定するときは、冒頭の「remote/」を省略することができます。

git rebase origin/main

 ↑↓ 同じ

git rebase remotes/origin/main


実例

例えば、以下のようなブランチの状態だとします。

$ git branch -a
  aa
  main
* test
  remotes/origin/HEAD -> origin/main
  remotes/origin/aa
  remotes/origin/main

このときに、現在のtestブランチにおいて、リモート追跡ブランチ「remotes/origin/aa」の内容をリベースで取り込みたい場合は以下のようにします。

$ git rebase origin/aa
Successfully rebased and updated refs/heads/test.

すると、git fetchしてきた最新のリモートレポジトリ「origin」の「aa」ブランチのコミット履歴を取り込むことができます。

合わせて読みたい

git rebaseの処理内容や詳細、コンフリクトが発生した場合の対処法については下記をご参考ください。

【Git】git rebase(リベース)とは何か?使い方を実例で解説

タイトルとURLをコピーしました