マージ後にgitが履歴を保存する方法について少し混乱しています。
ブランチA
をブランチにB
正常にマージしました。さて、B
マージの一部であるブランチ内のファイルに移動すると、ブランチのそのファイルのすべての履歴が表示されますが、ブランチの履歴は表示されA
ませんB
。ブランチ用のそのファイルの履歴はどこにありますB
か?
私が合併した方法は通り抜けていたgit merge <branch>
ので、この場合、私はブランチにいB
て使用しましたgit merge A
。
例えば、枝にA
私は、次のコミットを持っていた:a
、aa
、aaa
別のファイルに対応します。
支店ではB
、私は次のコミットを持っていた:b
、bb
、bbb
別のファイルに対応します。
私はブランチをマージしたときに今A
の枝にB
、すべての私はブランチに表示B git log
されているa
、aa
、aaa
歴史。自分のb
歴史がわかりません。
本質的には、私がマージするとき、私のマージがリニアになりたいA
しB
、私は歴史が分岐のすべてが欲しいB
の歴史を、歴史の上にそれだけでSVNはそれをしないのと同じように発生したことを、マージされます。
私の現在のgitログ履歴は非常に紛らわしいです。
歴史は消えていません、Gitはそれを示していません。
Gitでは、履歴は一連のコミットです。ファイル履歴はありません!
あなたのようなコマンドを実行するとgit log dir/sub/file.ext
、またはそのことについては、git log dir/sub
またはgit log .
中ながらdir/sub
、Gitはなり合成本当の歴史・コミットのセットからいくつかのサブ歴史を抽出することにより、(一時的な)ファイルの履歴を。この合成プロセスは、意図的にいくつかのコミットを削除します。たとえば、質問したファイルに影響を与えないすべてのコミットを削除します。ただし、デフォルトでは、History Simplificationとgit log
呼ばれるものを介して、それよりもはるかに多くの値がドロップされます。
すべてのコミットには一意のハッシュIDがあります。git log
たとえば、これらは出力に表示されます。ハッシュIDは、実際にはコミットの内容の暗号化チェックサムにすぎません。
各コミットはファイルのスナップショット(のハッシュID)を保存します—Gitはこれをツリーと呼びます。これはマージコミットにも当てはまります。マージコミットには、他のコミットと同様に、ツリーがあります。
各コミットには、名前(作成者とコミッター)、メールアドレス、タイムスタンプも保存されるため、Gitはこれらを表示できます。Gitがそれを表示できるように、ログメッセージを保存します。
Gitがコミットに保存する最後のもの(実際には、直後の2番目のもの)は、一意のハッシュIDによる親コミットのtree
リストです。
通常の非マージコミットを処理する場合、履歴を確認するのは非常に簡単です。のようなブランチ名で識別される最新のコミットから開始し、master
逆方向に作業します。ブランチ名には、最後のコミット(ブランチの先端)のハッシュIDが含まれ、ブランチ名はそのコミットを指していると言います。
... <--1234567... <--master
コミットした場合1234567
の先端であるmaster
、git log
あなたがコミット表示することができます1234567
...とコミット1234567
その中のハッシュIDは、それが右来るコミット持って前に 1234567
。
実際のハッシュIDを1文字に交換すると、作業が簡単になり、次のようになります。
A <-B <-C <-D <-E <-F <-G <--master
コミットG
ポイントをコミットF
に戻します。コミットはを指します。これはE
、最初のコミットであるコミットに到達するまで続きA
ます。このコミットはどこも指していません—それはできません、それは最初のコミットでした。親を持つことはできません。したがって、これは、時間の開始時に履歴が終了する(開始する?)場所です。Gitは呼び出すルートはコミット:なし親にコミットします。A
時間の終わりから始まり、始まりで終わる線形履歴を表示するのは簡単です。Gitは、各コミットを一度に1つずつ選択して表示するだけです。それは何です:
git log master
する:それは、で識別される1つのコミットで始まりmaster
、それを表示し、次に1つのコミットの1つの親を表示し、次にその前のコミットを表示します。
Gitにコミットを表示させると、実際には、ほとんどの場合、Gitにスナップショットではなくパッチとして表示させることができます。たとえば、git log --patch
これを行います。コミットをパッチとして表示するために、Gitは最初にコミットの親のツリーを調べ、次にコミットのツリーを調べて、2つを比較します。どちらもスナップショットであるため、親のスナップショットから子のスナップショットに変更されたものはすべて、子をコミットさせた人が実際に行ったものでなければなりません。
Gitが逆方向に機能することがわかったので、実際のマージコミットを含む履歴を含む、より複雑な履歴を見てみましょう。(git merge
常にマージされるとは限らないという事実に惑わされないようにしましょう!)
マージコミットは単に少なくとも二つの両親と一緒にコミットです。ほとんどの場合、3人以上の親とのコミットは表示されません。Gitはこれらのタコのマージを呼び出します。通常のマージでは実行できないことは何も行わないため、タコのマージは主にGit-fuを誇示するためのものです。:-)
通常、を実行することでマージを取得し、次のgit checkout somebranch; git merge otherbranch
ように結果のコミットチェーンを描画できます。
...--E--F--G------M <-- master
\ /
H--I--J <-- feature
ここで、実行するとしますgit log master
(注:--patch
オプションはありません)。もちろん、GitはM
最初にコミットすることを示す必要があります。しかし、Gitは次にどのコミットを表示しますか?J
、またはG
?それらのいずれかが表示されている場合、その後はどれを表示する必要がありますか?
Gitには、この問題に対する一般的な答えがあります。マージコミットが表示されると、コミットの両方の親を「まだ表示されていないコミット」のキューに追加できます。通常の非マージコミットが表示されると、(単一の)親が同じキューに追加されます。次に、キューをループして、一度に1つずつコミットし、その親をキューに追加することを示します。
履歴が線形の場合、キューには一度に1つのコミットが含まれます。1つのコミットが削除されて表示され、キューに1つの親が含まれるようになり、親が表示されます。
履歴にマージがある場合、キューは1つのコミットで始まり、Gitはコミットをキューからポップして表示し、両方の親をキューに入れます。次に、Gitは両親やショーあなたのうちの1つ選ぶG
かJ
、そしてプットF
またはI
キューにします。キューにはまだ2つのコミットがあります。Gitは1つをポップして、そのコミットを示し、もう1つをオンにします。
最終的に、GitはF
、F
がすでにキューにあるときにキューに入れようとします。Gitはこの場合の上映では、その最終的にキューの深さは1に減少し、再びコミットし、それを2回追加避けF
、E
、D
、など。(ここでの詳細は少し複雑です。キューは具体的には優先度キューであり、優先度は追加のgit log
並べ替えパラメーターによって決定されるため、これが発生する可能性のあるさまざまな方法があります。)
git log --graph
コマンドに追加する--graph
とgit log
、Gitは、子のコミットを親に接続する線を含む、やや大雑把なASCIIアートグラフを描画します。これはgit log
、一度に1つのコミットを表示している場合でも、表示しているコミット履歴が線形ではないことを伝えるのに非常に役立ちます(必須であるため)。
上記の-p
または--patch
で、親のスナップショット/ツリーを子のスナップショット/ツリーと比較することにより、コミットでgit log
何が変更されたかを示します。ただし、マージコミットの場合、2つ(またはそれ以上)の親があります。少なくとも2つの親があるため、親と子の比較を表示する方法はありません。
何をgit log
行い、デフォルトでは、完全にあきらめることです。パッチが表示されないだけです。他のコマンドはもっと複雑なことをします、そしてあなたもそれをするように説得git log
することができます、しかしデフォルトがgit log
ここで諦めることであることに注意しましょう。
git log
ドキュメントへのクリック可能なリンクです)を実行するとgit log file.ext
、Gitは、(親と子を比較して取得した)差分が接触しない非マージコミットを意図的にスキップしますfile.ext
。それは十分に自然なことです:あなたが次のようなチェーンを持っているなら:
A--B--C--D--E <-- master
file.ext
コミットを行ったときに変更した(または最初に作成した)A
とE
、これら2つのコミットだけを表示したいとします。Gitは、D
-vs-のパッチを見つけE
て、それがfile.ext
変更されたことを確認し(したがって、表示さ れるはずですE
)、に移動することでこれを行うことができますD
。C
-vs-D
比較ショーへの変更なしfile.ext
、Gitはしていないだろう示しD
、それが置かれますC
プライオリティキューにと訪問に行きますC
。それもファイルに変更がないため、Gitは最終的ににB
移動しA
ます。これは変更がなく、Gitはに移動します。比較のために、のすべてのファイルA
は常に新しいものです。これがルートコミットのルールです。すべてのファイルが追加されるため、Gitに表示されますA
同様に。
ただし、デフォルトでgit log
は、マージのパッチを計算することを好まないことがわかりました。難しすぎる!したがって、git log
通常、ここではマージは表示されません。ただし、コミットグラフの任意の部分を単純化しようとします。ドキュメントに記載されているように、デフォルトモードは次のとおりです。
最終結果が同じである場合、いくつかの側枝を剪定します...
コミットがマージであり、[ファイルがと同じ] 1つの親である場合は、その親のみをフォローします。...それ以外の場合は、すべての親に従ってください。
したがってM
、グラフのようなマージコミットでは、Gitは高速チェックを実行します。は?file.ext
と同じです。その場合は、キューに追加します。そうでない場合、それは同じであるのように?その場合は、キューに追加します。それ以外の場合、すなわち、で異なっているよりも、両方との両方を-addおよびキューに。M
G
G
M
J
J
file.ext
M
G
J
G
J
履歴の簡略化には他にもモードがあり、さまざまなフラグで選択できます。この回答はすでに長すぎるので、ドキュメントに任せます(上記のリンクを参照)。
Gitが実行する履歴の単純化のため、表示内容からあまり多くの推論を引き出すことはできません。すべてを表示したい場合は、代わりに実行することを検討してください。このオプションは、目的のために各マージを分割し(これはオプションに適用されます)、Gitに常にすべての親をフォローするように強制します。git log -- path
git log --full-history -m -p -- path
-m
git diff
-p
--full-history
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加