🦥

リモートに存在するはずのブランチにpushができない

に公開

結論

ローカルでブランチを作成して最初にリモートにpushした時に、ブランチの追跡設定を行っていなかったことが原因でした。
gitのメッセージにある通りgit push --set-upstream origin feature/xxx して、ローカルとリモートを紐づけてから push したら成功しました。

何がおきた

開発ブランチをローカルで作成、コードを修正後一度リモートにpush。
その後ローカルで別のコードを修正し、再度pushしようとしたら失敗しました。

fatal: The current branch feature/xxx has no upstream branch.
To push the current branch and set the remote as upstream, use
    git push --set-upstream origin feature/xxx
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

「カレントブランチ(= ローカルブランチ)には上流ブランチ(= リモートブランチ)がありません」と言われます。
しかし、リモートブランチにブランチは存在します。なぜこのようなことが起こるのでしょうか。

原因

gitのメッセージにあるように、追跡設定を行っていなかったのか確認しました。
シェルの履歴を出してみます。

$ history | grep git
534  git switch -c feature/xxx
535  git branch
536  git add .
537  git status
538  git commit -m "最初のコミット"
539  git branch
540  git push origin HEAD
...途中省略...
578  git branch
579  history | grep git

540番目が最初のpushですが、git push origin HEAD を打っていたことが判明、これが原因でした。

ローカルブランチがリモートブランチを追跡していない場合、git pushコマンドだけを実行すると失敗します。今回のように、ローカルでブランチを作成し、リモートに上げる場合が失敗するパターンの例です。
しかし、git push origin HEADは失敗せずにpushできてしまいます。そのため、追跡設定も行われると勘違いしていました。

ということで、gitのメッセージにある通り、--set-upstream オプションをつけて追跡設定を追加しました。

$ git push --set-upstream origin feature/xxx
Enumerating objects: 86, done.
Counting objects: 100% (86/86), done.
Delta compression using up to 12 threads
Compressing objects: 100% (45/45), done.
Writing objects: 100% (46/46), 7.32 KiB | 7.32 MiB/s, done.
Total 46 (delta 40), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (40/40), completed with 38 local objects.
To github.com:{リポジトリ名}
   f8887be0c..89259972d  feature/xxx -> feature/xxx
branch 'feature/xxx' set up to track 'origin/feature/xxx'.

ちなみに、--set-upstream のショートオプションは -u です。

おわりに

普段は --set-upstream オプションを使ってpushするのですが、最近ちゃんとGitコマンドを理解しようと中途半端に学んだ結果、間違ったコマンドを使ってしまいました。
また、いつもオプションを覚えられないのでgit pushを実行して一度失敗させ、gitのメッセージに出てきたコマンドをコピペして使うという怠惰な運用をしていました(ショートオプションの存在を知りませんでした)。
普段からサボらずちゃんとメッセージを読んでいたら、早い理解とこのようなトラブルは起きなかったかもしれません。

おまけ

ローカルで新規作成したブランチをリモートにpushする際によく使う追跡設定(--set-upstream)
ですが、逆に追跡を解除するオプションもあります(こちらはショートオプションはない)。

git branch --unset-upstream feature/xxx

いつ使うのだろうと思ったのですが、「リモートからクローンしてきてちょっとローカルでソースを見たい」という時、誤ってpushしないように使ったりするようです。なるほど。

Discussion