コード取得時にGitが実行する2つの処理方式
スプリントタスクで3つのファイルを編集している最中に、同僚からmainへホットフィックスをpushしたと連絡があったとします。すぐにそのパッチを取り込む必要があります。よく使うコマンドはgit pullですが、このコマンドの裏側で、Gitにはソースコードを統合するための全く異なる2つの仕組みが存在します。
1. デフォルトのGit Pull(マージ戦略)
デフォルトでは、ローカルに新しいコミットが存在する場合、git pullは中間コミットであるマージコミットを自動生成します。例えば、Merge branch 'main' of github.com:...のようなコミットです。
6〜8人ほどの開発チームで頻繁にコードをpushしていると、わずか1週間でgit log --graphはクモの巣のように入り組んだ状態になってしまいます。コミット履歴は激しく断片化し、バグ調査のためにgit bisectを使おうとしても、不要な枝分かれをいくつも辿らなければならず、調査に2倍の時間がかかってしまいます。
2. Rebaseフラグ付きのGit Pull
git pull --rebaseは異なるアプローチをとります。つまり、タイムラインを並び替えるアプローチです。
Gitはまずローカルのコミットを一時的に脇へ退避させます。次に、リモートの最新コミットをすべて先に取得します。最後に、退避させていたコミットをそのブランチの先頭に1つずつ積み直します。これにより、プロジェクトの履歴はきれいな直線(リニアヒストリー)を保ち、誰が見ても機能の開発順序が一目瞭然になります。
最大の難所:書きかけのコード(Dirty Working Tree)
問題は、pullする前にコミットすることは稀だという点です。大抵の場合、ローカルにはテスト用の書きかけコードが残っています。
未コミットの変更がある状態でgit pull --rebaseを実行すると、即座に処理が中断され、“error: cannot rebase: You have unstaged changes”というエラーが発生します。この場合、手動で行う手順はかなり面倒です。
git stashを実行してコードを一時退避する。git pull --rebaseを実行して最新コードを取得する。git stash popを実行して作業中のコードを復元する。
ステップ3をうっかり忘れると、コードが全部消えてしまったのかと青ざめることになります。
各ソリューションの直接比較
よくある3つのアプローチを比較したものが以下になります:
- デフォルトのpullをそのまま使用:使いやすく、コミットハッシュを書き換えないため初学者にも安全です。ただし、不要なマージコミットが大量に発生し(1スプリントあたり平均15〜30個の不要コミット)、リポジトリの履歴を濁らせてしまうデメリットがあります。
- 手動でpull –rebaseを実行:コミットツリーをクリーンかつ一直線に保てます。しかし、stash > pull > popという3つのコマンドを毎回実行するのは手間で、急いでいる時に手順を抜かしやすくなります。
- pull.rebaseとrebase.autoStashの併用:100%自動化されます。実行するコマンドは
git pullひとつだけです。Gitが自動的に作業中の変更を退避し、ブランチをrebaseした上で、コードを安全に復元してくれます。
チームへの実践的な導入経験
私が以前参加していた10人規模のFintechプロジェクトでは、クロスしたマージコミットに起因するコンフリクトの解消のためだけに、リリース直前に約3時間も費やしたことがありました。過去のコードが、レビュー済みの新しいコードを誤って上書きしてしまう事故も発生していました。
チーム全体でautoStash付きのrebase設定を有効にすることをルール化してからは、このような問題は一切なくなりました。コンフリクトの発生頻度は目に見えて減少し、Gitログのグラフが常に一直線になったことで、リードによるPRのレビューやリリースブランチへのcherry-pickが非常にスムーズになりました。
この設定は、特に次のような方に適しています:
- アジャイル/スクラム体制で開発しており、機能ブランチを頻繁に
developへrebaseする方。 - CI/CDでConventional Commitsに基づくチェンジログを自動生成するために、明瞭なログを維持したい方。
- 作業効率を上げ、日々の手動stash作業から解放されたい方。
詳細な設定手順
ターミナルを開き、以下の2つのコマンドを実行するだけです。この設定は初回に一度実行するだけで完了します。
マシン全体に適用する設定(グローバル設定 – 推奨)
# 1. git pullのデフォルト動作をrebaseに設定
git config --global pull.rebase true
# 2. rebase前に自動でstashし、完了後に自動で復元
git config --global rebase.autoStash true
特定プロジェクトのみに適用する設定(ローカル設定)
会社のリポジトリのポリシーでマージコミットを維持することが義務付けられている場合は、個人のプロジェクトに対してローカルでのみ適用してください:
cd /path/to/my-project
git config pull.rebase true
git config rebase.autoStash true
設定内容の確認
設定がGitに正しく反映されているか確認するには、次のコマンドを実行します:
git config --global --get-regexp "pull|rebase"
画面に以下のように出力されれば設定完了です:
pull.rebase true
rebase.autostash true
ターミナル上での実際の挙動
設定後、例えばservices/auth.goを編集したままコミットしていない状態を想定します。リモートに最新の変更が入った際も、実行するコマンドはこれだけです:
git pull
Gitがバックグラウンドですべての工程を自動処理してくれます:
Created autostash: 8f2c1b4
First, rewinding head to replay your work on top of it...
Fast-forwarded main to origin/main.
Applying autostash: 8f2c1b4
Applied autostash.
auth.goファイルは編集途中の状態がそのまま保持されます。リモートの新しいコミットもすべてスムーズに取り込まれ、コミット履歴は不要なマージコミットを1つも挟むことなく、すっきりと一直線の状態を維持できます。

