s やs と同じように、インデックスに何がgit
含まれているかについてはあいまいな考えがありますが、. 私は特に、マージが失敗した場合 (たとえば、何らかの競合が原因で) にインデックスが保持するものを知りたいと思っています。git-add
git-commit
git-merge
1 に答える
任意のパスに対して、インデックスには最大 4 つの「バージョン番号」があり、0 (ゼロ) から 3 までの番号が付けられています。すべてのエントリに実際に存在するかのようにそれらを「スロット」と呼び、簡単にインデックスを付けます (この実際には追加のバージョンは必要な場合にのみ動的に導入されますが。これらの「仮想スロット」は「空」である可能性があり、ファイルが存在しないことを意味します。
(実際には、エントリがインデックスに作成されると、CE_REMOVED
必要に応じてフラグ ビットでマークされます。これは、ファイルでいっぱいのディレクトリ全体が「削除済み」とマークされ、次の名前でファイルが作成される可能性があるため、毛むくじゃらになります。以前のディレクトリと「追加済み」とマークされた. 代わりに、固定スロットがあると仮定しましょう. :-) )
スロット #0 は、「通常の」、競合のない、万事順調なエントリです。これには、リポジトリに格納されているファイルの一連のキャッシュ データ、パス名、および blob-ID (SHA-1) が含まれています。
マージが成功すると、すべて「通常どおり」になるため、唯一の特殊なケースはマージの競合です。スロット 1、2、および/または 3 が空でない場合、マージは「競合」します。メカニズムのほとんどをスキップすると、何が起こるかというと、これです。マージでは、すべてのスロットに「最新」の名前が使用されます。
- スロット 0 は空のままです (競合を解決するまで「コミット」することはできません。競合を解決するまでは、ファイルを本当に削除したい場合を除き、このスロットはもう空ではありません)。
- スロット 1 (「ベース」) には、共通の祖先バージョンが入ります。ファイルが (両方のリビジョンで) 新しい場合、このスロットは空です。
- スロット 2 (「私たち」) は、ターゲット (
HEAD
基になるマージ機構の一部を手動で呼び出していない限り) バージョンで埋められます。/ target-of-merge でファイルが削除された場合、HEAD
代わりにこのスロットは空になります。 - スロット 3 ("theirs") には、マージされるバージョンが入ります。マージ中のリビジョンでファイルが削除された場合、このスロットは空です。
競合を解決して「git add」すると、#0 スロットは「追加」したもので埋められ、#1 から #3 のエントリが消去されます。または、競合しているファイルを「git rm」した場合は、他のステージ エントリは引き続き削除されますが、#0 スロットは空のままになり、競合も解決されます。
より具体的には、次の 2 つのファイルを持つ共通の祖先があるとします。
gronk
flibby
あなたはブランチcleanup
にいて、名前を に変更gronk
しbreem
、その と の両方を編集しましたflibby
。あなたは、彼らが変更したが名前を変更しなかったgit merge work
場所で、 を削除することにしました。他のいくつかのファイルはきれいにマージされました。gronk
flibby
インデックスには、 の 3 つのバージョンbleem
と の 2 つのバージョンが含まれflibby
ます。
$ git checkout cleanup
Switched to branch 'cleanup'
$ git merge work
CONFLICT (modify/delete): flibby deleted in work and modified
in HEAD. Version HEAD of flibby left in tree.
Auto-merging bleem
CONFLICT (content): Merge conflict in bleem
Automatic merge failed; fix conflicts and then commit the result.
$ git ls-files --stage
100644 4362aba7f3b7abf2da0d0ed558cbf5bc0d12e4b0 1 bleem
100644 49db92a61392e9fd691c4af6e1221f408452a128 2 bleem
100644 04b399c8fe321902ce97a1538248878756678ca2 3 bleem
100644 366b52546711401122b791457793a38c033838dd 1 flibby
100644 6fecb1480f45faaabc31b18c91262d03d3767cde 2 flibby
100644 7129c6edb96d08bb44ca1025eb5ae41d41be8903 0 x.txt
bleem
withのオリジナル (ベース) バージョンを見ることができますgit show :1:bleem
。これはgronk
基本バージョン (work
この場合は同様に) で呼び出されましたが、現在はbleem
git が in に名前が変更されたgronk
と認識しているため、呼び出されています。(この場合のように、Git はマージ ベース間の名前変更を検出し、必要に応じて同じ名前変更を適用します。)bleem
cleanup
HEAD
work
同様に、 または を含むバージョンと、 、 、または のいずれかを含むバージョンを確認できます(スロット2にはwork
akaバージョンが含まれ、の名前に従って名前が付けられます)。git show :3:bleem
git show work:gronk
HEAD
git show HEAD:bleem
git show cleanup:bleem
git show :2:bleem
HEAD
cleanup
HEAD
flibby
ただし、については、 で削除されたwork
ため、「彼らの」(スロット 3) バージョンはありません。
競合を解決するには、スロット 0 のエントリを更新して 1 ~ 3 のエントリを削除するだけgit add
ですgit rm
。もちろん、 ではgit add
、スロット 0 に入れるのは現在の作業ディレクトリにあるものなので、通常は最初にファイルを編集する必要があります。
ちなみに、スロット 2 と 3 には、上記で「私たちのもの」と「彼らのもの」というラベルを付けました。これはgit checkout
、それらを同様に処理する方法です (git checkout --ours
そしてgit checkout --theirs
、バージョン 2 または 3 をスロット 0 に書き込むことができます。このようなチェックアウトは、ほとんどのチェックアウトと同様に、他のスロットも「消去」し、競合を解決します)。ただし、リベースでは、HEAD
ブランチは実際にはリベース先のブランチであり、「彼らの」バージョンはリベース先のブランチです。したがって、私の意見では、私たちの/彼らの用語はそれほど素晴らしいものではありません.リベース中に元に戻すのは簡単すぎます.
また、競合するマージの最中にある場合は、必要に応じてスロット 0 を消去し、スロット 1 ~ 3 のバージョンを「復活」させることによって、マージの競合を「再作成」することに注意してくださいgit checkout -m
(競合するマージを作成します)。ファイルを作業ディレクトリにコピーし、merge.conflictstyle
設定の変更にも従います)。