故障中:
実際、リモートリポジトリでも動作する git rev-list に相当するものを見つけたいと思っています。
1つもありません。一部のリモートに含まれていないコミットの数を確認したい場合、これは以下で重要です。
実際、私はリモート サーバー上の特定のブランチが特定のローカル ブランチと異なるかどうかを判断しようとしています。異なる場合は、関係がどのようになっているのか (早送り可能、前方、後方、分岐)。...最初に取得せずにそのような比較を行う方法はありますか?
まあ、主にいいえ、ただし、これは、ここでどの程度文字通りになりたいか、および結果がどれだけ正確に必要かによって部分的に異なります. また、リモートから切断して更新を取得した直後に、他の誰かが同じリモートに接続してすべてを変更する可能性があることに注意してください。リモートも1 つしかないかのように作成しました。複数のリモートがある場合があります。
を使用git fetch
すると、リモートに接続し、参照 (主にブランチ ヘッドとタグだけでなく、git ノートなども含む) に関してクエリを実行し、必要に応じて新しいものを持ち込みます。
を使用git ls-remote
すると、リモートへの接続が確立され、クエリが実行されます (そして、そこで停止します)。
したがって、リモートに「到達しにくい」場合 (たとえば、接続の確立に 1 ~ 2 秒かかる、または ssh パスワードやフレーズなどの入力が必要) であるが、更新が小さいか高速である (接続が確立されると、転送はfetch
後で 2 番目の接続を作成するのは面倒なので、単純な方が経済的です。「簡単にアクセスできる」が、更新が大きくて遅い場合は、ls-remote
. しかし、いずれにせよ、リモートへの接続を行っています。これは、 fetch
. また、中間のコミット ID を一覧表示する必要がある場合は、それらのコミットを持ち込む必要があるため、完全に実行する必要がありますfetch
。
もう 1 つのしわがありfetch
ます。
git ls-remote
サンプル出力を見てみましょうgit remote show origin
。最初に実行しますgit fetch origin
(ただし、既に最新であるため、出力はありません)。
$ git fetch origin
$ git ls-remote origin
120a630b0b71193a33cd033ae9ddcee1db3df07e HEAD
120a630b0b71193a33cd033ae9ddcee1db3df07e refs/heads/master
$ git remote show origin
* remote origin
Fetch URL: ssh://[host]//tmp/tt.git/
Push URL: ssh://[host]//tmp/tt.git/
HEAD branch: master
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (fast-forwardable)
(ここHEAD branch
に示されているのは推測であり、通常は無視する必要があります。HEAD
すべての の SHA-1 に対して の SHA -1 を照合することによって計算されrefs/heads/*
ます。正確に 1 つの一致がある場合にのみ正しいことが保証されます。2 つまたはより多くの一致がある場合、誤って正しい可能性がありますが、これを確実に機能させるには、git でプロトコルを変更する必要があります。)
URL はそれぞれ fromgit config --get remote.origin.url
およびgit config --get remote.origin.pushurl
です (何も設定されていない場合、デフォルトのプッシュ URL はフェッチ URL と同じです)。
では、その理由を見てみましょうmaster merges with remote master
。これは、次の 2 つの構成項目によるものです。
$ git config --get branch.master.remote
origin
$ git config --get branch.master.merge
refs/heads/master
(後者の設定には、おそらく歴史的な事故である、いくつかの深い奇妙さがあります。git merge のドキュメントを読むと、次のように表示されます。
branch.<current branch>.merge
によって名前が付けられたリモートのブランチの名前の値branch.<current branch>.remote
が参照され、対応するリモート追跡ブランチにマップされremote.<remote>.fetch
、これらの追跡ブランチのヒントがマージされます。
「正常な」構成では (git fetch
以下の注を参照)、これはrefs/heads/master
上記が実際に意味することを意味しrefs/remotes/origin/master
ます。)
また、master pushes to master
この特定のケースでgit config push.default matching
は、このリポジトリに設定したため、push.default
. 新しいバージョンの git を使用している場合、および/または を設定push.default
していない場合、または別の方法で設定している場合は、別のバージョンにプッシュされる可能性があります。現在可能な値はnothing
、current
、upstream
、simple
およびmatching
です。git-config のドキュメントを参照してください。
ここで、このプッシュが早送りである理由について説明します。ls-remote
出力から、リモートrefs/heads/master
(つまり、master
プッシュ先) が参照していることがわかります120a630b0b71193a33cd033ae9ddcee1db3df07e
。すでにご存じのように (おそらく気付いていないかもしれませんが)、私たちが持っていて、彼らが持っていないものを見ることができます:
$ git rev-list 120a630b0b71193a33cd033ae9ddcee1db3df07e..master
eed7b697cab0cbd5babf382f720668e12a86cf2a
224384fed46e1949c88eb514fa67743be66a4c5a
ddc0aab680bab0bd6a7dde4a6ef8cb58ba0368e6
ade842c8562cdccd1e98f7ffd5149a12ddc9226c
4 つのコミットがありますが、そうではありません。そして、git fetch
これらすべてを開始する前に実行し、適切な構成を持っているため、私たちが持っていないものを確認できます。
$ git rev-list master..120a630b0b71193a33cd033ae9ddcee1db3df07e
それは何もありません。もう 1 つ知っておく必要があります。実際、これから始めるべきです。つまり、「120a630...
実際にはmaster
( ade842c...
) の祖先ですか、そうでない場合は、それと私たちの間に共通の祖先がありますmaster
か?」ということです。ここでは、省略形の SHA-1 と名前master
を長さとして使用します。
$ if git merge-base --is-ancestor 120a630 master; then echo OK; fi
OK
—したがって、これは「早送り可能」です。つまり、4 より進んで 0 より遅れています。(実際、先祖であることは、遅れていないことを直ちに意味します。の出力ls-remote
。)
120a630
が の祖先でない場合master
、それは 2 つのことのいずれかを意味します。たぶん、私たちのmaster
は彼らmaster
の . または、おそらくより可能性が高いのは、それらが私たちのすぐ前にある (早送りできる) か、次のようなコミット グラフ フラグメントを持つ共通の祖先がある場合です。
D--E--F
/
A--B--C
\
G--H
(たとえば、C
は共通の祖先であり、それらは にF
あり、私たちは にあり、リベースまたはマージできます)。H
それを見つけるには、彼らmaster
と逆方向に作業を開始し、私たちmaster
と逆方向に作業を開始して、それらがある時点で一致するかどうかを確認する必要があります。willを使用git merge-base
してポイントを見つけることができますが、これはmaster
commit-IDだけでなく、そのポイントまでF
の中間 ID (D
と) も必要であることを意味します。E
これもまた、する必要があることを意味しgit fetch
ます。
を実行するgit fetch
と、それらrefs/heads/master
が にある120a630b0b71193a33cd033ae9ddcee1db3df07e
ことを検出するだけでなく、必要なコミット (ない場合もあれば、多くの場合もあります) も取得されますgit rev-list
。
を使用すると、 git 参照も set にgit fetch
更新されます。しかし、それは次の理由だけです。refs/remotes/origin/master
$ git config --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
この構成項目はfetch
、参照のリストを取得した後 (同じものがls-remote
出力されます)、一致するものを取得しrefs/heads/*
、名前を に変更し、refs/remotes/origin/<match>
それらをローカルリポジトリに詰め込む必要があることを示しています。
これは変更できるため、更新されgit fetch
ませんorigin/master
。誰かがそれを行った場合、git rev-list origin/master..master
役に立ちません。D
(そして、コミット、E
、およびいずれかを取得できるかどうかはわかりませんF
! クレイジーなフェッチ構成で実行したことはありません。)
要約すると、次のことを理解する必要があります。
- 接続するリモート (ある場合)
- これらのリモートに対応するローカル ブランチ (
refs/heads/*
) (プルおよび/またはプッシュ)
- 彼らの支部長が私たちの支部長と関係があるかどうか (同じ名前か別の名前か)
matching
プッシュが同じ名前 ( , current
, simple
-if-name-same ) にプッシュされるか、潜在的に別の名前 ( upstream
) にプッシュされるか、「決して」プッシュされないか ( nothing
, simple
-if-name-different )
- 一部またはすべてのリモートに接続しないことを選択した場合に、参照を信頼するかどうか
refs/remotes/
(行に基づく)remote.name.fetch
push
とfetch
が非対称であるため、すべて非常に面倒です。git push blarg
がプッシュされる可能性がありますmatching
(したがって、blarg
という名前のブランチがある場合、セットがなくても、そこにglink
プッシュします)。構成変数、などもあります。その他の構成も同様です (再度、git-config のドキュメントを参照してください)。glink
glink
branch.glink.remote
remote.pushdefault
remote.name.push
fetch
git fetch
( を実行してから、おそらく を使用するのが最善だと思いますgit branch -vv
。)