Git入門:バージョン管理のきほん
clone と fetch の違い
この回でやること
リポジトリをまるごと複製する clone と、リモートの最新情報だけを取ってくる fetch を区別します。origin/main というリモート追跡ブランチの正体を理解して、安全に状況を確認できるようになりましょう。
- 読む 約 8 分
最新にしたくて clone し直すと、手元の作業が置き去りになる
GitHub 上のリポジトリを手元に持ってくるとき、最初に打つのが git clone です。内部では 3 つのことが行われています。ディレクトリを作って Git リポジトリとして初期化し、リモートの全履歴をダウンロードしてそのリモートに origin という別名を登録し、既定のブランチをチェックアウトして作業ファイルを並べる。だから clone の直後からファイルが見えます。
ターミナル
$ git clone git@github.com:example/myapp.git
Cloning into 'myapp'...
Receiving objects: 100% (142/142), 24.31 KiB, done.clone を使うのは最初の 1 回だけです。 更新したいと思って再び clone すると、別のディレクトリにまったく別のコピーができます。手元のコミットしていない作業も設定も引き継がれません。すでにリポジトリがあるなら、更新は必ず fetch か pull です。
origin/main は、リモートを見に行っていない
clone した直後の git log に、見慣れない名前が並びます。
ターミナル
$ git log --oneline -1
8a2f4e6 (HEAD -> main, origin/main) 検索 API のレスポンスを整形main と origin/main が同じコミットを指していますが、この 2 つは別物です。origin/main はリモート追跡ブランチと呼ばれ、役割は 1 つだけです。最後にリモートと通信したとき、リモートの main がどのコミットを指していたかを記録すること。
大事なのは、これがリモートを覗く窓ではない点です。手元に保存された、前回の通信結果のメモにすぎません。だからオフラインでも読めますし、他の人が GitHub へ push しても、あなたが fetch するまで origin/main は動きません。
手元の main は自分がコミットしたときに進み、origin/main は fetch や pull のときだけ進む。この違いを押さえてください。
fetch しただけで、取り込んだつもりになる
ターミナル
$ git fetch
From github.com:example/myapp
8a2f4e6..c7d1b93 main -> origin/main
$ git status
Your branch is behind 'origin/main' by 1 commitorigin/main が進みました。そしてそれ以外は何も変わっていません。手元の main は元のままで、作業中のファイルは 1 文字も書き換わりません。編集途中のファイルがあっても、fetch は文句を言いません。
多い失敗が、この出力を見て「取ってきた」と思い、そのまま作業を続けることです。他の人の修正は反映されていないので、数時間後の push で弾かれ、大きくなった差分を解決するはめになります。fetch の後は必ず git status を打ってください。behind と出ていれば、まだ取り込んでいません。
fetch の価値は、取り込む前に相手の変更を確認できることにあります。
ターミナル
$ git log --oneline main..origin/main
c7d1b93 パスワードの最小文字数を 12 に変更main..origin/main は「main には無くて origin/main にあるコミット」の指定で、降ってくるものが分かります。同じファイルを自分も編集していると分かれば、先にコミットする、stash で退避する、といった手を打てます。いきなり pull すると、この判断の機会がないまま解決作業に放り込まれます。
- clone は複製とリモート登録と初回チェックアウトをまとめてやる。使うのは最初の 1 回だけ
origin/mainは最後に通信したときの位置を記録したメモで、リアルタイムのリモートではない- fetch は取ってくるだけで、手元のブランチにも作業ファイルにも触らない
- fetch のあとは
git statusとgit log main..origin/mainで中身を確かめる