これは正確には本当の答えではありませんが、フォーマットへのアクセスと多くのスペースが必要です。私が2つの最良の答えと考えるものの背後にある理論を説明しようと思います:受け入れられたものと(少なくとも現在)トップランクのものです。しかし実際には、彼らはさまざまな質問に答えます。
Gitでのコミットは、一度に複数のブランチで「オン」になることがよくあります。確かに、それは質問が何であるかについての多くです。与えられた:
...--F--G--H <-- master
\
I--J <-- develop
大文字が実際のGitハッシュIDを表す場合、出力でコミットのみHまたはコミットI-Jのみを検索することがよくありgit logます。までのコミットGは両方のブランチにあるので、それらを除外したいと思います。
(注このように描かれたグラフに、新しいコミットは右の方にあること。名前は、単一の一番右がその行にコミットを選択し、それらのコミットのそれぞれは、その左にコミットしているコミット、親、があります。の親HですG、およびの親はJですI。の親IはG再びです。の親GはF、でFあり、ここには表示されていない親があります。これは、の一部です。...セクション。)
この特に単純なケースでは、次のものを使用できます。
git log master..develop # note: two dots
表示するにはI-J、または:
git log develop..master # note: two dots
表示Hのみ。2つのドットの後の右側の名前は、Gitに次のように伝えます。はい、これらはコミットします。2つのドットの前の左側の名前は、Gitに次のように伝えます。いいえ、これらのコミットではありません。Gitは最後から始まります—コミット時Hまたはcommit)逆方向にJ機能します。これについての(多くの)詳細については、Think Like(a)Gitを参照してください。。
元の質問の言い方では、目的は、から到達可能なコミットを見つけることです。ある特定の名前が、同じ一般的なカテゴリの他の名前かられます。つまり、より複雑なグラフがある場合:
O--P <-- name5
/
N <-- name4
/
...--F--G--H--I---M <-- name1
\ /
J-----K <-- name2
\
L <-- name3
name4またはなどのこれらの名前の1つを選択して、次のname3ように尋ねることができます。その名前ではどのコミットを見つけることができますが、他の名前では見つけることができませんか? 私たちが選ぶならname3、答えはコミットLです。を選択したname4場合、答えはコミットではありません。name4名前はコミットですNが、コミットNはで開始しname5て逆方向に作業することで見つけることができます。
受け入れられた回答は、ブランチ名ではなくリモートトラッキング名で機能しorigin/merge-only、選択した名前として1つ(スペルト小麦)を指定して、その名前空間内の他のすべての名前を確認できます。また、マージの表示を回避name1します。「興味深い名前」として選択し、name1他の名前ではなく到達可能なコミットを表示すると、マージコミットMと通常のコミットが表示されIます。
最も人気のある答えはまったく異なります。これは、グラフをコミットトラバースに関するすべてだせずに、次の両足、およびマージのを示すことなく、コミットのいずれかのあるマージを。たとえば、で始まるname1場合、表示されませんM(マージです)が、マージの最初の親MがcommitIであると仮定すると、commitJとK。も調べません。私たちは、コミット示す終わるだろうI、ともコミットH、G、F、など、いずれもこれらのマージコミットしていると、すべてがで開始することにより到達可能Mと後方作業だけ訪れる最初の各マージの親がコミット。
最も人気のある答えは、たとえば、masterいつ見るのに非常に適していますmasterマージのみのブランチになるのかを。すべての「実際の作業」がサイドブランチで行われmaster、その後にマージされた場合、次のようなパターンになります。
I---------M---------N <-- master
\ / \ /
o--o--o o--o--o
ここで、文字名のないすべてのoコミットは通常の(非マージ)コミットでありM、およびNはマージコミットです。コミットIは最初のコミットです。これまでに行われた最初のコミットであり、マージコミットではないマスター上にある必要がある唯一のコミットです。場合git log --first-parent --no-merges masterのショーは、任意のコミット以外の Iような状況になります。
I---------M----*----N <-- master
\ / \ /
o--o--o o--o--o
コミットを見たい場所 *master一部の機能ブランチをマージするのではなく、で直接行われた。
要するに、人気のある答えは見るのに最適です masterいつmasterマージのみが意図されているかのに最適ですが、他の状況にはそれほど適していません。 受け入れられた答えは、これらの他の状況で機能します。
リモートトラッキングの名前は次のようなものですか origin/master ブランチの名のですか?
Gitのいくつかの部分はそうではないと言います:
git checkout master
...
git status
言う on branch masterが:
git checkout origin/master
...
git status
と言いHEAD detached at origin/masterます。私はgit checkout/に同意することを好みgit switchます:でorigin/masterはありませんブランチ名であなたがそれに「乗る」ことができないので。
受け入れられた回答は、リモート追跡名を使用していますorigin/*を「ブランチ名」として。
git log --no-merges origin/merge-only \
--not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
grep -Fv refs/remotes/origin/merge-only)
を呼び出す中央の行 git for-each-ref、名前の付いたリモートのリモート追跡名を繰り返し処理し。origin。
これは元の問題に良い解決策である理由は、私たちがここに興味を持っているということである誰かの支店名ではなく、私たちのブランチ名。しかし、それはブランチを以外のものとして定義したことを意味します私たちのブランチ名。それは問題ありません。これを行うときは、これを行っていることに注意してください。
git log コミットグラフの一部をトラバースします
ここで私たちが本当に探しているのは、私がダグレットと呼んでいる一連のことです。「ブランチ」とは正確にはどういう意味ですか?を参照してください。 つまり、私たちは探していますコミットグラフ全体のサブセット内のフラグメントをます。
Gitに、のようなブランチ名、のようなmasterタグ名v2.1、またはのようなリモートトラッキング名を見てもらうときはいつでも、origin/masterGitにそのコミットと、そのコミットから取得できるすべてのコミットについて教えてもらいたいと思う傾向があります。 、および逆方向に作業します。
数学では、これはグラフのウォーキングと呼ばれます。Gitのコミットグラフは有向非巡回グラフまたはDAGであり、この種のグラフは特に歩行に適しています。このようなグラフを歩くときは、使用されているパスを介して到達可能な各グラフの頂点にアクセスします。Gitグラフの頂点はコミットであり、エッジは円弧(一方向のリンク)であり、各子から各親に移動します。(これはThink Like(a)Gitが登場します。アークの一方向の性質は、Gitが子から親へと逆方向に機能する必要があることを意味します。)
グラフ・ウォーキング用の2つのメインのGitコマンドがあるgit logとgit rev-list。これらのコマンドは非常に似ており、実際にはほとんど同じソースファイルから構築されていますが、出力は異なります。git log人間が読み取るgit rev-listための出力を生成し、他のGitプログラムが読み取るための出力を生成します。1 どちらのコマンドも、この種のグラフウォークを実行します。
彼らが行うグラフウォークは具体的には次のとおりです。 です。開始点コミットのセット(おそらく1つのコミット、ハッシュIDの束、ハッシュIDに解決される名前の束)を指定して、グラフをウォークし、コミットにアクセスします。特定のようなディレクティブ、--notまたはプレフィックス^、または--ancestry-path、または--first-parent、修正グラフ徒歩何らかの方法でを。
グラフウォークを行うとき、各コミットにアクセスします。ただし、ウォークされたコミットの選択されたサブセットのみを出力します。印刷をコミットするグラフウォーキングコードなどのディレクティブまたは指示--no-merges--before <date>。
この訪問を行うために、一度に1つのコミットで、これら2つのコマンドは優先キューを使用します。git logまたはgit rev-listを実行し、それにいくつかの開始点コミットを与えます。それらのコミットを優先キューに入れます。たとえば、単純なもの:
git log master
名前masterを生のハッシュIDに変換し、その1つのハッシュIDをキューに入れます。または:
git log master develop
両方の名前をハッシュIDに変換し、これらが2つの異なるハッシュIDであると仮定して、両方をキューに入れます。
このキュー内のコミットの優先度は、さらに多くの引数によって決定されます。たとえば、引数--author-date-orderはgit logまたはgit rev-list使用することを著者はむしろコミッタのタイムスタンプよりも、タイムスタンプを。デフォルトでは、コミッターのタイムスタンプを使用し、日付ごとに最新のコミット(数値の日付が最も高いコミット)を選択します。したがって、でmaster develop、これらが2つの異なるコミットに解決されると仮定すると、Gitはどちらが後で来たかを表示しますそれがキューの先頭になりますので、最初に。
いずれにせよ、リビジョンウォーキングコードはループで実行されるようになりました。
- キューにコミットがある間:
- 最初のキューエントリを削除します。
- このコミットを印刷するかどうかを決定します。たとえば、
--no-merges:マージコミットの場合は何も出力しません。--before:日付が指定時刻より前でない場合は何も印刷しません。印刷が抑制されていない場合は、コミットを印刷します。git logします。for、ログを表示します。の場合git rev-list、ハッシュIDを出力します。
- このコミットの親コミットの一部またはすべてをキューに入れます(現在そこになく、まだアクセスされていない場合2)。通常のデフォルトでは、すべての親を入力します。を使用
--first-parentすると、各マージの最初の親を除くすべてが抑制されます。
(両方ともgit log、親の書き換えの有無にかかわらず、履歴の簡略化をgit rev-list行うことができますこの時点でますが、ここではスキップします。)
マージコミットがない場合に開始しHEADて逆方向に作業するような単純なチェーンの場合、キューには常にループの先頭に1つのコミットがあります。コミットが1つあるので、それをポップして印刷し、その(単一の)親をキューに入れて再び回り、最初のコミットに到達するか、ユーザーが飽きるまでチェーンを逆方向にたどります。git log出力終了プログラム。この場合、どの順序オプションも重要ではありません。表示するコミットは1つだけです。
マージがあり、両方の親(マージの両方の「レッグ」)に従う場合、git logまたはgit rev-list複数の開始コミットを指定する場合、並べ替えオプションが重要になります。
最後に、コミット指定子の効果--notまたはその^前を検討します。これらには、それらを書くためのいくつかの方法があります。
git log master --not develop
または:
git log ^develop master
または:
git log develop..master
すべて同じことを意味します。これ--notは^、複数の名前に適用されることを除いて、プレフィックスに似ています。
git log ^branch1 ^branch2 branch3
ブランチ1ではなく、ブランチ2ではなく、ブランチ3ではないことを意味します。だが:
git log --not branch1 branch2 branch3
は、branch1、branch2、branch3ではないことを意味し、1秒--notを使用してオフにする必要があります。
git log --not branch1 branch2 --not branch3
これは少し厄介です。2つの「not」ディレクティブはXORを介して結合されるため、本当に必要な場合は、次のように記述できます。
git log --not branch1 branch2 ^branch3
意味しない支社、ないBRANCH2を、branch3はい、あなたがしたい場合は難読化。
これらはすべて、グラフウォークに影響を与えることによって機能します。通りgit logやgit rev-listグラフを歩く、それは確かになりませんいずれかの任意のから到達可能であることをコミットプライオリティキューに入れるために否定参照。(実際、これらはセットアップの開始にも影響します。否定されたコミットは、コマンドラインから直接優先キューに入れることができないgit log master ^masterため、たとえば何も表示されません。)
gitrevisionsのドキュメントで説明されているすべての凝った構文はこれを利用しており、を呼び出すだけでこれを公開できますgit rev-parse。例えば:
$ git rev-parse origin/pu...origin/master # note: three dots
b34789c0b0d3b137f0bb516b417bd8d75e0cb306
fc307aa3771ece59e174157510c6db6f0d4b40ec
^b34789c0b0d3b137f0bb516b417bd8d75e0cb306
3ドットの構文は、左側または右側から到達可能なコミットを意味しますが、両方から到達可能なコミットは除外します。この場合、origin/masterコミット b34789c0b、、自体はorigin/pu(fc307aa37...)から到達可能であるため、origin/masterハッシュは2回表示され、1回は否定が表示されますが、実際には、Gitは2つの正の参照(2つの否定されていないハッシュID)を入力することで3ドット構文を実現します。によって表される1つの否定的なもの^接頭辞。
同様に:
$ git rev-parse master^^@
2c42fb76531f4565b5434e46102e6d85a0861738
2f0a093dd640e0dad0b261dae2427f2541b5426c
^@構文手段与えられたすべての親がコミット、およびmaster^自体ブランチ名が選択したコミットの最初の親はmaster、それが両親を持っているので、マージコミット-is。これらは2人の親です。そして:
$ git rev-parse master^^!
0b07eecf6ed9334f09d6624732a4af2da03e38eb
^2c42fb76531f4565b5434e46102e6d85a0861738
^2f0a093dd640e0dad0b261dae2427f2541b5426c
^!接尾手段は、自分自身をコミットしていないが、その親のどれ。この場合、master^は0b07eecf6...です。^@接尾辞が付いた両方の親をすでに見ました。ここに再びありますが、今回は否定されました。
1多くのGitプログラムは文字通り実行されますgit rev-listさまざまなオプションでれ、その出力を読み取って、使用するコミットやその他のGitオブジェクトを認識します。
2グラフは非循環であるため、まだアクセスされていないことを保証できます。制約を追加すると、すべての子を優先度に表示する前に親を表示しないようにします。 --date-order、--author-date-order、そして--topo-orderこの制約を追加します。デフォルトのソート順(名前はありません)にはありません。コミットのタイムスタンプが厄介な場合(たとえば、クロックがオフになっているコンピューターによって「将来」にコミットが行われた場合)、これにより、出力が奇妙に見える場合があります。
あなたがこれまでにそれを成し遂げたならば、あなたは今について多くを知っています git log
概要:
git log グラフの一部またはすべてを歩きながら、選択したコミットを表示することです。
--no-merges引数には、いくつかのコミットを示す、受け入れられ、現在トップランクの答えを抑制し、両方で見つかっているが歩いたし。
--first-parent現在トップランクの回答からの議論は、歩行を抑制しますは、グラフウォーク自体の間にグラフの一部をするます。
--not受け入れられた回答で使用されているコマンドライン引数のプレフィックスは、最初からグラフの一部にアクセスすることをまったく抑制します。
これらの機能を使用して、2つの異なる質問に対する好きな答えを得ることができます。
git log ^branch1 ^branch2 merge-only-branchです。構文を使用しないのはなぜですか。