なぜ「git push --set-upstream origin」を実行する必要があるのか "? 質問する

なぜ「git push --set-upstream origin」を実行する必要があるのか

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

ベストアンサー1

要約: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 では、 を実行するたびに、Git は大量のノイズを吐き出して、黙らせるためだけにgit pushを設定するよう説得しようとしていました。push.defaultgit push

実行している Git のバージョンや を設定したかどうかについては言及されていないpush.defaultため、推測するしかありません。私の推測では、Git バージョン 2-point-something を使用していて、それを黙らせるために を に設定しているのでしょう。長くて退屈な歴史があるため、使用している Git のバージョンと、設定している場合のその内容はpush.default重要です、結局のところ、Git からまた別の苦情を受けているという事実は、過去の間違いの 1 つを回避するように Git が設定されていることを示しています。simplepush.default

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

アップストリームは、単に別のブランチ名であり、通常はリモート追跡ブランチであり、(通常のローカル)ブランチに関連付けられています。

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

アップストリームは有効なブランチである必要がありますが、そうである必要はありません ( のようなリモート追跡ブランチでも、 のようなローカル ブランチでも)。つまり、現在のブランチBにアップストリームUがある場合、は機能します。これが機能しない場合 (つまり、Uが存在しないというエラーが表示される場合)、Git のほとんどはアップストリームがまったく設定されていないかのように動作します。 などのいくつかのコマンドは、アップストリーム設定を表示しますが、それを「消失」としてマークします。origin/Bmastergit rev-parse U git branch -vv

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

がまたはpush.defaultに設定されている場合、アップストリームの設定により、追加の引数なしで使用される が機能するようになります。simpleupstreamgit push

以上です。 の場合、これがすべてです。しかし、 は単純なタイプミスが大きな問題を引き起こす場所の 1 つであるgit pushため、これはかなり重要です。git push

が、、またはpush.defaultに設定されている場合、アップストリームを設定しても には何も影響しません。nothingmatchingcurrentgit push

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

上流の影響git fetch

git fetch追加の引数なしで実行すると、Git は現在のブランチのアップストリームを参照して、どのリモートからフェッチするかを判断します。アップストリームがリモート追跡ブランチの場合、Git はそのリモートからフェッチします。(アップストリームが設定されていないか、ローカル ブランチの場合、Git は のフェッチを試みますorigin。)

上流の影響git mergegit rebase

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

上流の影響git pull

とにかく2 は使用すべきではありませgit pullんが、使用する場合は、git pullアップストリーム設定を使用して、どのリモートからフェッチするかを判断し、どのブランチをマージまたはリベースするかを判断します。つまり、 はgit pullと同じことを行いますgit fetch(実際には が実行 されるため)。その後、またはgit fetchと同じことを行います (実際にはまたはが実行されるため) 。git mergegit rebase git mergegit rebase

(少なくとも、Git を十分に理解して、どちらかのステップが失敗したときに (最終的には失敗するでしょうが)、何が間違っていたのかを認識し、どう対処すればよいかがわかるようになるまでは、通常、これら 2 つのステップを手動で実行する必要があります。)

上流の影響git status

これは実際には最も重要かもしれません。アップストリームを設定したら、git statusコミットの観点から、現在のブランチとそのアップストリームの違いを報告できます。

通常の場合と同様に、Bアップストリームが に設定されているブランチにいるときに を実行すると、プッシュできるコミットや、マージまたはリベースできるコミットがあるかどうかがすぐに表示されます。origin/Bgit status

これは、次の実行が原因ですgit status

  • git rev-list --count @{u}..HEADB:にないコミットはいくつありますか?origin/B
  • git rev-list --count HEAD..@{u}:にないコミットはいくつありますか?origin/BB

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

なぜmasterすでにアップストリームセットがあるのですか?

最初にリモートからクローンを作成するときは、次のようにします。

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

または同様の場合、Git が行う最後のステップは、基本的に、 ですgit checkout master。これにより、ローカル ブランチがチェックアウトされます。ただし、ローカル ブランチはありmasterません。master

一方、という名前のリモート追跡ブランチは存在しますorigin/masterこれは、クローンしたばかりだからです。

Git は、次のように意味していると推測します: 「masterremote-tracking と同じコミットを指す新しいローカルを作成しorigin/master、ついでに、 のアップストリームを に設定しますmasterorigin/master

これは、まだ作成していないすべてのブランチに対して発生しますgit checkout。Git はブランチを作成し対応するリモート追跡ブランチを「追跡」 (アップストリームとして作成) します。

しかし、これは新しいブランチ、つまりリモート追跡ブランチがまだないブランチでは機能しません。

新しいブランチを作成する場合:

$ git checkout -b solaris

現時点では、 はありませんorigin/solaris。リモート追跡ブランチが存在しないため、ローカルでは追跡solaris できません。origin/solaris

新しいブランチを初めてプッシュするとき:

$ git push origin solaris

は上に を作成し 、したがって自分の Git リポジトリにも を作成します。しかし、もう遅すぎます。すでにアップストリームのないローカル が存在ます。3solarisoriginorigin/solarissolaris

Git はそれを自動的にアップストリームとして設定するべきではないでしょうか?

おそらくそうです。「実装が不十分」と脚注 1 を参照してください。今変更するのは困難です。Git を使用するスクリプトは数百万4あり、その一部は Git の現在の動作に依存している可能性があります。動作を変更するには、新しいメジャー リリース、構成フィールドの設定を強制するナグウェアなどが必要です。つまり、Git は自身の成功の犠牲者です。現在 Git にどのような間違いがあっても、その修正は、変更がほとんど目に見えないか、明らかに大幅に改善されているか、時間をかけてゆっくりと行われるかのいずれかでなければできません。

実際のところ、中にまたは を使用しない限り、今日ではそうではありません。 これがメッセージが伝えている内容です。--set-upstream-ugit push

そのようにする必要はありません。上で述べたように、まったくそうする必要はありませんが、アップストリームが必要だとします。以前のプッシュを通じてsolarisにブランチを既に作成しており、出力に示されているように、ローカル リポジトリにはすでに があります。origingit branch origin/solaris

のアップストリームとして設定されていないだけですsolaris

最初のプッシュ時ではなく、今すぐ設定するには、 を使用しますgit branch --set-upstream-to--set-upstream-toサブコマンドは、 などの既存のブランチの名前を受け取りorigin/solaris、現在のブランチのアップストリームをその他のブランチに設定します。

それがすべてです。それがすべてですが、上記で述べたすべての意味合いがあります。つまり、 を実行しgit fetch、確認してから、必要に応じて または を実行し、新しいコミットを作成して を実行すれgit mergeばよく、追加の手間がかかりません。git rebasegit push


1公平に言えば、当初の実装がエラーを起こしやすいことは当時は明らかではありませんでした。新しいユーザーが毎回同じ間違いを犯したときに初めてそれが明らかになりました。今では「それほど悪くはない」ですが、「素晴らしい」とは言えません。

2「絶対に」というのは少し言い過ぎですが、ステップを分けて説明すると、特に実際に何が行われたかを示し、次に何が行われるか、または行われる予定git fetchかがわかると、Git 初心者は物事をはるかgit mergeによく理解できると思います。git rebase

3最初の git pushasを実行する場合git push -u origin solaris、つまりフラグを追加する場合、プッシュが成功した場合のみ、-uGit は現在のブランチのアップストリームとして設定します。したがって、最初のプッシュで指定する必要があります。実際、それ以降のプッシュで指定することができ、その時点でアップストリームが設定または変更されます。ただし、忘れた場合は、その方が簡単だと思います。origin/solaris-ugit branch --set-upstream-to

4とにかく、オースティン・パワーズ/ドクター・イービルの方法で測定すると、単に「1ミルル・ユン」と言うだけです。

おすすめ記事