次の git コマンドの使用の違いは何ですか
git pull オリジン マスター
git pull オリジン マスター:マスター
いくつかの観察
1)最初のものは競合があるかどうかを教えてくれますが、もう一方は単に「拒否されました-早送りではありません」と言っています
2) 2 つ目は、失敗した場合、リモート ポインター、つまり origin/master を更新しません。
これは少し難しいので、1 つずつ処理していきましょう。
git pull
次のようにロールします。
指定された refs 1 (例の 2 番目の引数、refspecと呼ばれる「参照仕様」のポートマニュー) を指定されたリモート (例の最初の引数) から取得します。
リモート引数が欠落している場合、Git はbranch.<name>.remote
ローカル リポジトリの構成変数を使用してそれを取得しようとします。ここ<name>
で、 は現在チェックアウトされているブランチの名前です。
refspec 引数が欠落している場合、Git はbranch.<name>.merge
ローカル リポジトリの構成変数を使用してそれを取得しようとします<name>
。これは、上記と同じことを意味します。
フェッチされたすべての参照を現在チェックアウトされているブランチにマージするため、@ Oznerol256 は正しくありません。
それでは、 refspecmaster
と…の違いについて説明しましょう。master:master
git pull
git pull
refspec を に直接渡しgit fetch
、次の方法で refspec を解析します: 「の左側の仕様に一致するすべての参照をリモートから取得し、:
おそらくそれらを使用して、仕様で指定されたローカル リポジトリ内の一致する参照を更新します。 "の右側にあり:
ます。ここで重要なの:
は、refspec に no がない場合、またはその右側に何もない場合、これは によって「何も更新しない」と解釈されることgit fetch
です。
では、さらに掘り下げてみましょう。refspecs の解釈規則によれば、裸の "master" は (ほとんどの場合2 ) として解釈されますrefs/heads/master
。これは、"«master» という名前のブランチ" を意味します。
さて、次のことは明らかですgit pull origin master
。
で示されるリモートからgit fetch origin master
取得する呼び出しで、取得したオブジェクトをデータベースに格納するだけです (さらに、特別な ref を更新します)。ローカル リポジトリのブランチやタグは更新されません。refs/heads/master
origin
FETCH_HEAD
リモート リポジトリからフェッチされた状態を、現在チェックアウトされているブランチgit merge FETCH_HEAD
にマージしようとする呼び出し。refs/heads/master
明らかに、これにより競合が発生する可能性があり、それが最初のケースで観察されていることです。
では、さらに深く掘り下げてみましょう。今では明らかなように、master:master
refspec (通常は2 ) は に展開されるためrefs/heads/master:refs/heads/master
、次のようにgit pull origin master:master
ロールします。
それはgit fetch origin master:master
どちらを呼びます
refs/heads/master
リモートから取得し、 refs/heads/master
フェッチされたオブジェクトによってローカルに更新します。
ローカルの「マスター」がリモートの「マスター」に完全に含まれていない場合、これは「非早送り」エラーで失敗する可能性があり、それがあなたが観察していることです。
最初のステップでエラーが発生したため、この時点ではマージは試行されません。
どちらの例もローカル参照を適切に更新しないことに注意してください。最初のものはこれを試みず、2番目のものは間違っていると思われる参照を更新しようとします — 正しい呼び出しは、git pull origin +refs/heads/master:refs/remotes/origin/master
強制的に(したがって+
)適切なものを更新しますリモートブランチを作成し、フェッチされたものを現在チェックアウトされているブランチにマージしようとします。
git fetch origin
このような「奇妙な」refspec が使用される理由を理解するために、呼び出し時に Git が使用するremote.<remotename>.fetch
refspecを見てみましょう。git remote add
git clone
$ git config --local --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
ご覧のとおり、git fetch
更新を強制し、リモート ブランチを更新するように指示します。
git pull
内部の仕組みを実際に理解することなく、頻繁に無意識に使いすぎていることが今では見られます。私の意見では、引っ張る代わりに2段階の操作を使用する方がはるかに優れています。
git fetch origin
— リモートブランチを更新します。git merge origin/master
— 「オリジン」で最後に確認された「マスター」の状態を、現在チェックアウトされているブランチにマージします。
現在チェックアウトされているブランチが、マージするリモート ブランチを追跡するように設定されている場合、Git 呼び出しはさらに簡単になります。
git merge @{u}
この記事を読むこともお勧めします。
1 Git 用語の「ref」は、コミット (単純または直接参照) または別の参照 (シンボリック ref — はシンボリック ref ) を指す名前付きHEAD
エンティティです。ブランチとタグは単純な ref の例であり、HEAD
両方である可能性があります。ブランチをチェックアウトした場合、それはシンボリック ref であり、他のものをチェックアウトした場合 (したがって「切り離された HEAD」状態にある場合)、それは単純な ref です。
2タグと「master」という名前のブランチがある場合、refspec はタグの名前として解決されます — タグが優先されます。このような状況では、完全な参照名を使用してブランチを指定できます。
はgit pull
本質的に 2 つの操作を実行します。最初にgit fetch
、続いてgit merge
です。
を使用すると、リモートgit pull origin master
のmaster
ブランチorigin
が取得 (取得) され、現在のチェックアウトされたブランチにマージされます。
2 つのブランチ名を定義することで、どのブランチがどのブランチにマージされるかのrefspecを指定しています。
一般化された例は次のとおりです。「指定されたリモートからソース ブランチを取得し、それを宛先ブランチとマージします。
git pull <remote> <source>:<destination>