1. ホーム
  2. ギット

[解決済み】なぜ「git push --set-upstream origin <branch>」をしなければならないのでしょうか?

2022-04-20 15:15:07

質問

SolarisとSun Studioをテストするためにローカルブランチを作成しました。その後、そのブランチを上流にプッシュしました。変更をコミットしてプッシュしようとしたところ、次のようなエラーが発生しました。

$ git commit blake2.cpp -m "Add workaround for missing _mm_set_epi64x"
[solaris 7ad22ff] Add workaround for missing _mm_set_epi64x
 1 file changed, 5 insertions(+)
$ git push
fatal: The current branch solaris has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin solaris

なぜ、こんなにも特別なことをしなければならないのでしょうか?

を作成するような合理的なユースケースはあるのだろうか? <branch> をプッシュしてください。 <branch> をリモートで実行し、その後 <branch> は、本来は <branch> ?


Stack Overflowのこの質問と答えに従いました。 新しいローカルブランチをリモートの Git リポジトリにプッシュし、それを追跡する . 私は、これが不完全な、または間違った受け入れの答えの別の例であると推測しています。あるいは、Gitが単純な作業を難しくしている例もあります。


別のマシンでの表示です。ブランチは明らかに存在するので、作成されてプッシュされました。

$ git branch -a
  alignas
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/alignas
  remotes/origin/arm-neon
  remotes/origin/det-sig
  remotes/origin/master
  remotes/origin/solaris

解決方法は?

TL;DR: git branch --set-upstream-to origin/solaris


あなたの質問に対する答えは、「上流を設定する必要があるか」と言い換えると、「いいえ、ありません」です。 があります。 を設定する必要は全くありません。

しかし、現在のブランチのアップストリームがない場合、Git はその挙動を git push そして、他のコマンドでも同様です。

ここでの完全なプッシュの話は長く退屈で、歴史はGitバージョン1.5以前までさかのぼります。 それを大幅に短縮するために git push は実装が貧弱でした。 1 Gitバージョン2.0から、Gitは設定ノブのスペルが push.default に変更され、デフォルトは simple . 2.0以前のいくつかのバージョンのGitでは、2.0以降では git push を設定するよう説得するために、Git はたくさんのノイズを吐き出しました。 push.default を取得するためだけに git push を黙らせる。

どのバージョンのGitを使用しているのか、または push.default そのため、推測する必要があります。 私の推測では、Git のバージョン 2-point-something を使っていて push.default から simple を実行して、黙らせることができます。 どのバージョンのGitを使用しているのか、また、どのようなものがあるのかを正確に教えてください。 push.default に設定してください。 が行います。 しかし結局のところ、Git からまた別の苦情を受けるということは、あなたの Git の 過去の失敗を回避するように設定されています。

アップストリームとは何ですか?

を意味します。 アップストリーム は単に別のブランチ名で、通常は (通常のローカル) ブランチに付随するリモート追跡ブランチです。

すべてのブランチには、1つの上流を設定するオプションがあります。 つまり、すべてのブランチは、上流を持つか、上流を持たないかのどちらかです。 どのブランチも2つ以上のアップストリームを持つことはできません。

上流 が必要です。 である必要はありませんが、有効なブランチである必要があります(リモートトラッキングのように origin/B または、以下のようなローカル master ). つまり、もし現在のブランチ B は上流に U , git rev-parse U べき が動作します。 動作しない場合、つまり U が存在しない場合、ほとんどのGitは上流が全く設定されていないかのように振る舞います。 いくつかのコマンド、たとえば git branch -vv は、上流の設定を表示しますが、それを "gone"としてマークします。

アップストリームは何の役に立つのか?

もし、あなたの push.default が設定されています。 simple または upstream の場合、上流側の設定により git push を追加引数なしで使用すると、そのまま動作します。

これだけです。 git push . しかし、これはかなり重要なことで、なぜなら git push は、単純なタイプミスが大きな頭痛の種になる場所の1つです。

もし、あなたの push.default が設定されています。 nothing , matching または current に対して、アップストリームを設定しても全く意味がありません。 git push .

(これらはすべて、Gitのバージョンが少なくとも2.0であることを前提としています)。

上流の影響 git fetch

を実行した場合 git fetch を追加引数なしで実行すると、Git は どの リモートから取得するには、現在のブランチのアップストリームを調べます。 上流がリモート追跡ブランチである場合、Git はそのリモートからフェッチします。 (アップストリームが設定されていない場合やローカルブランチの場合、Git は origin .)

上流の影響 git mergegit rebase

を実行すると git merge または git rebase を追加引数なしで指定すると、Git は現在のブランチのアップストリームを使用します。 そのため、このふたつのコマンドの使用頻度を減らすことができます。

上流が影響するのは git pull

決して 2 使用 git pull をどうせやるなら、でも、やるなら git pull は、上流の設定を使ってどのリモートから取得するか、 そしてどのブランチでマージやリベースを行うかを決定します。 つまり git pull と同じことをします。 git fetch -なぜなら、それは実際に 実行 git fetch -と同じことをします。 git merge または git rebase というのは、実際には 実行 git merge または git rebase .

(少なくとも、どちらかのステップが失敗したとき (いずれ失敗する)、何が悪かったのかがわかり、それに対してどうすべきかがわかるほど Git をよく知るまでは、通常はこのふたつのステップを手動で行うべきです)。

上流の影響 git status

実はこれが一番重要かもしれません。 上流が決まったら git status は、現在のブランチとその上流との間のコミット数の差を報告します。

通常のケースとして、あなたがブランチ B で、その上流が origin/B を実行すると git status を実行すると、プッシュできるコミットや、マージやリベースができるコミットがあるかどうかがすぐにわかります。

これは git status が実行されます。

  • git rev-list --count @{u}..HEAD に何回コミットしていますか? B にないものを origin/B ?
  • git rev-list --count HEAD..@{u} に何回コミットしていますか? origin/B にないものは B ?

アップストリームを設定することで、これらのことが可能になります。

どうして master はすでに上流に設定されているのですか?

どこかのリモートから初めてクローンするときに、使用します。

$ git clone git://some.host/path/to/repo.git

などで、Gitが行う最後のステップは、基本的には git checkout master . これはローカルブランチをチェックアウトするものです master -ただ、あなたは があります。 ローカルブランチ master .

一方、あなたは する という名前のリモートトラッキングブランチがあります。 origin/master というのも、あなたはそれをクローンしただけだからです。

Git は、あなたが言ったのは次のような意味だろうと推測しています: "新しいローカルを作れ master と同じコミットを指しており、リモートトラッキングの origin/master の上流を設定し、ついでに masterorigin/master ."

この現象は すべての ブランチ git checkout をまだ持っていない場合。 Git はブランチ 対応するリモート追跡ブランチを "track"(上流として持つ)ようにします。

しかし、これは 新しい ブランチ、つまりリモート追跡ブランチのないブランチは まだ .

を作成すると 新しい ブランチを作成します。

$ git checkout -b solaris

はまだありません。 origin/solaris . あなたのローカル solaris できない トラックリモートトラッキングブランチ origin/solaris が存在しないためです。

新しいブランチを最初にプッシュしたとき。

$ git push origin solaris

その クリエイト solaris について origin を作成し、その結果 origin/solaris を自分の Git リポジトリに追加します。 しかし、それでは遅すぎます。すでにローカルの solaris その は上流がない . 3

Gitは、今、自動的にそれを上流に設定すべきではないでしょうか?

おそらく。 実装が悪い" と脚注1を見てください。 を変更するのは難しいです。 現在 : 数百万人いる 4 を使うスクリプトのいくつかは、Gitの現在の動作に依存している可能性があります。 動作を変えるには、新しいメジャー・リリースが必要ですし、設定フィールドを強制的に設定させるためのナグ・ウェアも必要です。 要するに、Gitはそれ自身の成功の犠牲者なのです。今日、Gitにあるどんな間違いも、その変更がほとんど目に見えないか、明らかにずっと良いものか、時間をかけてゆっくりと行われるかのいずれかでなければ、修正することができないのです。

実は、今日はないんです。 ただし を使用します。 --set-upstream または -u の間に git push . それが、このメッセージの意味するところです。

そんな風にする必要はないんです。 まあ、上に書いたように、全くする必要はないのですが、例えば、次のような場合です。 欲しい 上流にある あなたはすでにブランチ solarisorigin は、以前のプッシュによって、そしてあなたの git branch の出力が示すように、あなたはすでに ある origin/solaris をローカルリポジトリに保存してください。

の上流に設定されていないだけです。 solaris .

最初のプッシュ時ではなく、今すぐ設定したい場合は git branch --set-upstream-to . その --set-upstream-to サブコマンドは、既存のブランチの名前をとります。 origin/solaris そして、現在のブランチの上流をその別のブランチに設定します。

これだけなのだが、上に書いたような意味合いがある。 つまり git fetch を実行し、周りを見渡して、次に git merge または git rebase を実行し、新しいコミットを作成します。 git push を使えば、余計な手間がかかりません。


1 公平に見て、当時は最初の実装がエラーを起こしやすいものであることは明らかではありませんでした。 それが明らかになったのは、新しいユーザーが毎回同じ失敗をするようになってからです。 現在では、quot; less poor"ですが、quot; great"とは言い切れません。

2 Never"はちょっと強いですが、Git の初心者は手順を分けたほうが理解しやすいと思います。 git fetch 実際に行ったことで、彼らは git merge または git rebase が次に行います。

3 を実行すると 最初 git push として git push -u origin solaris -を追加した場合。 -u フラグが設定されます。 origin/solaris を現在のブランチの上流として指定します。これは、プッシュが成功した場合のみです。 そのため -u の上で 最初 をプッシュします。 実際、それ以降のプッシュで供給することも可能で、その場合は または その時点で上流の しかし、私は git branch --set-upstream-to の方が簡単だと思います、忘れた方は。

4 オースティン・パワーズ/ドクター・イーブル方式で、「ワン・ミリオン・ユン」と言うだけ。