0

次の git コマンドの使用の違いは何ですか

git pull オリジン マスター
git pull オリジン マスター:マスター

いくつかの観察

1)最初のものは競合があるかどうかを教えてくれますが、もう一方は単に「拒否されました-早送りではありません」と言っています

2) 2 つ目は、失敗した場合、リモート ポインター、つまり origin/master を更新しません。

4

3 に答える 3

7

これは少し難しいので、1 つずつ処理していきましょう。

git pull次のようにロールします。

  1. 指定された refs 1 (例の 2 番目の引数、refspecと呼ばれる「参照仕様」のポートマニュー) を指定されたリモート (例の最初の引数) から取得します。

    リモート引数が欠落している場合、Git はbranch.<name>.remoteローカル リポジトリの構成変数を使用してそれを取得しようとします。ここ<name>で、 は現在チェックアウトされているブランチの名前です。

    refspec 引数が欠落している場合、Git はbranch.<name>.mergeローカル リポジトリの構成変数を使用してそれを取得しようとします<name>。これは、上記と同じことを意味します。

  2. フェッチされたすべての参照を現在チェックアウトされているブランチにマージするため、@ Oznerol256 は正しくありません。

それでは、 refspecmasterと…の違いについて説明しましょう。master:mastergit pull

git pullrefspec を に直接渡しgit fetch、次の方法で refspec を解析します: 「の左側の仕様に一致するすべての参照をリモートから取得し、:おそらくそれらを使用して、仕様で指定されたローカル リポジトリ内の一致する参照を更新します。 "の右側にあり:ます。ここで重要なの:は、refspec に no がない場合、またはその右側に何もない場合、これは によって「何も更新しない」と解釈されることgit fetchです。

では、さらに掘り下げてみましょう。refspecs の解釈規則によれば、裸の "master" は (ほとんどの場合2 ) として解釈されますrefs/heads/master。これは、"«master» という名前のブランチ" を意味します。

さて、次のことは明らかですgit pull origin master

  1. で示されるリモートからgit fetch origin master取得する呼び出しで、取得したオブジェクトをデータベースに格納するだけです (さらに、特別な ref を更新します)。ローカル リポジトリのブランチやタグは更新されません。refs/heads/masteroriginFETCH_HEAD

  2. リモート リポジトリからフェッチされた状態を、現在チェックアウトされているブランチgit merge FETCH_HEADにマージしようとする呼び出し。refs/heads/master

    明らかに、これにより競合が発生する可能性があり、それが最初のケースで観察されていることです。

では、さらに深く掘り下げてみましょう。今では明らかなように、master:masterrefspec (通常は2 ) は に展開されるためrefs/heads/master:refs/heads/master、次のようにgit pull origin master:masterロールします。

  1. それはgit fetch origin master:masterどちらを呼びます

    1. refs/heads/masterリモートから取得し、
    2. refs/heads/masterフェッチされたオブジェクトによってローカルに更新します。

      ローカルの「マスター」がリモートの「マスター」に完全に含まれていない場合、これは「非早送り」エラーで失敗する可能性があり、それがあなたが観察していることです。

最初のステップでエラーが発生したため、この時点ではマージは試行されません。

どちらの例もローカル参照を適切に更新しないことに注意してください。最初のものはこれを試みず、2番目のものは間違っていると思われる参照を更新しようとします — 正しい呼び出しは、git pull origin +refs/heads/master:refs/remotes/origin/master強制に(したがって+)適切なものを更新しますリモートブランチを作成し、フェッチされたものを現在チェックアウトされているブランチにマージしようとします。

git fetch originこのような「奇妙な」refspec が使用される理由を理解するために、呼び出し時に Git が使用するremote.<remotename>.fetchrefspecを見てみましょう。git remote addgit clone

$ git config --local --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*

ご覧のとおり、git fetch更新を強制し、リモート ブランチを更新するように指示します。

git pull内部の仕組みを実際に理解することなく、頻繁に無意識に使いすぎていることが今では見られます。私の意見では、引っ張る代わりに2段階の操作を使用する方がはるかに優れています。

  1. git fetch origin— リモートブランチを更新します。
  2. git merge origin/master— 「オリジン」で最後に確認された「マスター」の状態を、現在チェックアウトされているブランチにマージします。

    現在チェックアウトされているブランチが、マージするリモート ブランチを追跡するように設定されている場合、Git 呼び出しはさらに簡単になります。

    git merge @{u}
    

この記事を読むこともお勧めします。


1 Git 用語の「ref」は、コミット (単純または直接参照) または別の参照 (シンボリック ref — はシンボリック ref ) を指す名前付きHEADエンティティです。ブランチとタグは単純な ref の例であり、HEAD両方である可能性があります。ブランチをチェックアウトした場合、それはシンボリック ref であり、他のものをチェックアウトした場合 (したがって「切り離された HEAD」状態にある場合)、それは単純な ref です。

2タグと「master」という名前のブランチがある場合、refspec はタグの名前として解決されます — タグが優先されます。このような状況では、完全な参照名を使用してブランチを指定できます。

于 2013-09-13T13:36:53.317 に答える
0

git pull本質的に 2 つの操作を実行します。最初にgit fetch、続いてgit mergeです。

を使用すると、リモートgit pull origin mastermasterブランチoriginが取得 (取得) され、現在のチェックアウトされたブランチにマージされます。

2 つのブランチ名を定義することで、どのブランチがどのブランチにマージされるかのrefspecを指定しています。

一般化された例は次のとおりです。「指定されたリモートからソース ブランチを取得し、それを宛先ブランチとマージします。

git pull <remote> <source>:<destination>

于 2013-09-13T13:37:57.003 に答える