第6章 push と pull

ローカル、リモート、リモート追跡ブランチ

前章で origin という名前のリモートを設定した。ここで登場人物を整理しておく。

「ローカルの main」と「origin/main」はぜんぜん別のブランチである。 手元でコミットを積むと、ローカル main だけが前進する。 誰かが GitHub 側で main を更新しても、git fetch するまで手元の origin/main は古いままである。

push で GitHub に送る

初回 push の -u

前章で git remote add origin ... したばかりの状態では、ローカル main はまだどのリモートブランチとも紐づいていない。 初回だけ -u (--set-upstream の短縮形) を付けて、「このローカル mainorigin/main を追いかけるよ」という関係を記録する。

Bash
git push -u origin main

2 回目以降

一度 upstream が紐づけば、以降は引数なしで OK。Git はどのリモートのどのブランチに送ればいいかを自分で判断してくれる。

Bash
git push
注意

リモートが自分のローカルより先に進んでいる状態で git push しようとすると、! [rejected] というエラーで断られる。 これは「君の手元は古い。先に pull してから出直して」という意味のサイン。後述する pull で最新を取り込んでから push し直せばよい。 間違っても、慌てて --force を付けないこと。他人のコミットを押しつぶす事故になる。

pull で GitHub から受け取る

他の人が GitHub の main にコミットを積んだあと、自分も同じ最新状態に追いつきたい。 そのときに打つのが git pull。たった 1 つのコマンドに見えて、実は 2 段階の処理がまとまっている。

Bash
git pull
# これは実質↓と同じ
# git fetch
# git merge origin/main

fetch だけしたいとき

「ひとまずリモートの状態だけ見たい。merge するかどうかは差分を確認してから決めたい」という場面もある。 その場合は git fetch だけ打てばよい。

Bash
# リモートの最新を取得 (マージはしない)
git fetch

# ローカル main と origin/main の差分を確認
git log main..origin/main --oneline
POINT

チームによっては git pull のデフォルト挙動を rebase (マージコミットを作らず履歴を直列に並べ直す) にそろえる流儀もある。 git config --global pull.rebase true でその動作になる。プロジェクトのポリシーに合わせて選ぶとよい。

よくあるトラブルの入り口

push が rejected される

「リモートが先行している」が原因。git pull で最新を取り込み、コンフリクトがあれば解消してから git push。 コンフリクト解消の作法は発展編で詳しく扱う。

Permission denied (publickey)

SSH 鍵が GitHub 側に登録されていない、あるいは鍵のパーミッションがおかしい、が定番。 ssh -T git@github.com で挨拶が返ってこないなら、前章の手順を見直す。

リモートがずれてきた気がする

git fetch してから git status を打つと、「Your branch is behind 'origin/main' by N commits」のように、 ローカルとリモート追跡ブランチの関係を Git が教えてくれる。 迷子になったと感じたら、まず git fetch + git status で現在地を確認するのが近道である。

まとめ