Dev Study
← Gitの内部構造から理解する コース

12. push と fetch — リモートとの間で何が運ばれるのか

最後に、リモートリポジトリ(GitHub、GitLab、AWS CodeCommitなど)との同期を見ます。ホスティング先が変わっても、運ばれるものは同じです。

① 運ばれるのは「相手が持っていないオブジェクト」と「refの更新」

git push で起きること
① 相手のrefの位置を聞くどのコミットまで持っているか
差分を計算
② 不足しているオブジェクトだけ送るpackfileにまとめて圧縮
転送が終わったら
③ 相手のブランチファイルを新しいハッシュに更新これが成功して初めてpush完了
  • ・送るのはオブジェクトとrefの更新だけ。差分パッチではない
  • ・既に相手が持っているオブジェクトは送られない(ハッシュで判定できる)
  • ・GitHubでもCodeCommitでも、このプロトコルは共通

内容ベースの管理なので、「相手が持っているか」をハッシュの照合だけで判定できます。だから2回目以降のpushは軽くなります。

② pushが拒否されるのは「早送りできない」とき

non-fast-forward で弾かれる状況
リモートのmainが先に進んでいる他の人がpushした
自分のmainはその変更を含んでいない
早送りで更新できない → 拒否強行すると他人のコミットが参照されなくなる
正しい対処
git pull(fetch + merge/rebase)してから push相手の変更を取り込んでから送り直す
  • ・fast-forwardの判定はローカルのマージと全く同じ理屈
  • ・--force はリモートのrefを強制的に書き換える。他人の作業を参照から外しうる
  • ・fetchはリモート追跡ブランチを更新するだけで、作業ツリーは変えない

pushの拒否は事故防止です。第4部で見たfast-forwardの条件が、そのままリモート側でも判定されているだけだと分かれば、対処に迷いません。

サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗