作業ブランチでプッシュしたはずが、親ブランチにpushされていた件を深掘りしてみる
大山です。
先日、Claude にブランチを作ってもらいながら作業を進めていたところ、作業ブランチではなく親ブランチ(develop)に直接 push してしまう事案が発生しました。そのことについて深掘りした内容を記事にしようと思います。
何が起きたか
作業の流れはこうです。
- Claude に作業ブランチを作ってもらい、コミットも任せた
- push だけは自分が GitHub Desktop で行った
- 気づいたら親ブランチ(
develop)にコミットが積み上がっていた
git branch -vv で確認すると:
* feature/xxx abc1234 [origin/develop] コミットメッセージ
本来 [origin/feature/xxx] と表示されるべきところに、親ブランチのリモート [origin/develop] と出ていました。この状態で push したため、コミットがすべて origin/develop に流れ込んでいました。
なぜ起きたか
原因は2つが重なっていました。
原因①:Claude が origin 起点でブランチを切った
Claude に GitHub の認証情報を与えてないため git fetch が失敗し、「ローカルの develop が最新でないかもしれない」と判断して、リモートの origin/develop を直接起点にしてブランチを作ったとのこと。
git switch -c feature/xxx origin/develop
リモートブランチを起点にすると、そのリモートブランチが自動的に upstream として設定されます。つまり [origin/develop] がフィーチャーブランチの追跡先になってしまいました。
原因②:GitHub Desktop が CLI の安全策を通らなかった
本来、CLI で git push(引数なし)を実行した場合、Git 2.0 以降のデフォルト設定(push.default=simple)では、現在のブランチ名と upstream のブランチ名が異なるとエラー になります。(詳細は検証セクションにて)
しかし、GitHub Desktop から push した場合、この CLI レベルのエラーが通らず、upstream をそのまま使って push が実行されました。Claude 側も「push は CLI でやるだろう、その時にエラーが出るはず」と考えていたため、upstream の設定を確認しないまま作業を渡してしまいました。
この件はIssueとして上がっていましたが、特にこの仕様の進展はなさそうです。https://github.com/desktop/desktop/issues/2188
検証:リモートの親ブランチを起点にブランチを切ると何が起きるか
git switch -c feature/test origin/main
コマンドを実行した直後、upstream の設定がターミナルに表示されます。
branch 'feature/test' set up to track 'origin/main'.
Switched to a new branch 'feature/test'
git branch -vv で確認すると:
* feature/test 03988de [origin/main] コミットメッセージ
[origin/main] と表示されており、upstream が親ブランチのリモートに設定されています。
この状態で git push を CLI から実行すると、push.default=simple の安全策によってエラーになります。
$ git push
fatal: The upstream branch of your current branch does not match
the name of your current branch. To push to the upstream branch
on the remote, use
git push origin HEAD:main
To push to the branch of the same name on the remote, use
git push origin HEAD
CLI では止まりますが、GitHub Desktop はこの安全策を通らずに push を実行します。
upstream先がorigin

upstream先がリモートブランチ

UI上ではupstreamの表示がされていますが、ここを確認せずにpushしてしまいました。
branch.autoSetupMerge=simple にした場合
branch.autoSetupMerge を simple に変更して同じ操作をすると挙動が変わります。
git config --global branch.autoSetupMerge simple
git switch -c feature/test-simple origin/main
git branch -vv で確認すると:
feature/test 03988de [origin/main] コミットメッセージ
* feature/test-simple 03988de コミットメッセージ
feature/test-simple には [origin/main] が表示されていません。ブランチ名(feature/test-simple)とリモートブランチ名(main)が一致しないため、upstream が自動設定されませんでした。
upstream tracking とは何か
upstream tracking とは
Git には「このローカルブランチはリモートのどのブランチと対応しているか」を記録する仕組みがあります。これが upstream tracking(追跡設定)です。
upstream が設定されていると:
git push(引数なし)→ upstream に push されるgit pull(引数なし)→ upstream から pull されるgit status→ upstream との差分(ahead / behind)が表示される
設定項目:push.default
Git 2.0 以降、push.default のデフォルト値は simple に変更されました。
git config --global push.default # 現在の設定を確認
| 設定値 | 挙動 |
|---|---|
simple(デフォルト) |
upstream と同名のブランチにのみ push。名前が違えばエラー |
current |
upstream の設定に関わらず、現在のブランチ名でリモートに push(feature/xxx → origin/feature/xxx) |
upstream |
upstream に名前が違っても push(upstream が origin/develop なら develop に push される。危険) |
matching |
同名のローカルとリモートが存在するすべてのブランチに push(古い挙動) |
nothing |
常に明示的な指定が必要。引数なしは常にエラー |
simple のおかげで、今回のようなケースでは CLI でエラーになります。ただしこれは CLI の話であり、GUI ツールによってはこの制御が効かないことがあります。
設定項目:branch.autoSetupMerge
リモートブランチを起点にブランチを切ったとき、そのリモートを upstream として自動設定するかどうかを制御します。
git config --global branch.autoSetupMerge # 現在の設定を確認
| 設定値 | 挙動 |
|---|---|
true(デフォルト) |
リモートブランチを起点にした場合のみ upstream を自動設定 |
simple |
ブランチ名が一致する場合のみ自動設定(名前が違えば設定しない) |
always |
ローカルブランチを起点にした場合も upstream を自動設定しようとする |
inherit |
起点ブランチに tracking 設定があれば、それをそのまま新しいブランチにコピーする |
false |
自動設定しない |
simple に設定すれば、今回の事故のように origin/develop を起点に feature/xxx を切っても upstream が設定されなくなります。ただし毎回 git push -u origin feature/xxx が必要になります。
まとめ
- リモートの親ブランチ(
origin/develop)を起点にgit switch -cでブランチを切ると、親ブランチのリモートが upstream として設定される - CLI の
git pushはpush.default=simpleの安全策でエラーになるが、GitHub Desktop 等の GUI ツールはこのエラーが通らない場合がある - Agentに操作を任せる場合、push は CLI で行うか、push 前に
git branch -vvで upstream を確認する習慣をつけると防げる
Agentに操作を任せる上で基本知識は大事だなと改めて思いました。






