gpt4 book ai didi

git - git索引的内容在 merge 期间如何演变( merge 失败后索引中的内容)?

转载 作者:太空狗 更新时间:2023-10-29 13:20:59 25 4
gpt4 key购买 nike

我对git索引包含的内容与git-addgit-commit所包含的内容有一个模糊的想法,但是我不知道当执行git-merge时这些内容会发生什么。我特别想了解 merge 失败时(例如由于某些冲突)索引的内容。

最佳答案

对于任何给定的路径,索引中最多有四个“版本号”,编号为0(零)到3。我将它们称为“插槽”,就好像它们实际存在于每个条目中一样,然后轻松地进行索引(此索引使它们更容易考虑),尽管实际上只有在需要时才动态引入额外的版本。这些“虚拟插槽”可以为“空”,表示该文件不存在。

(实际上,一旦在索引中创建了一个条目,就会在必要时用一个标志位CE_REMOVED进行标记。这很麻烦,因为可以将整个文件目录标记为“已删除”,然后可以使用以下名称创建文件:上一个目录并标记为“已添加”。让我们假装我们有固定的插槽,那里是空的,而不是。:-))

插槽#0是“正常”,无冲突,完好无损的条目。它包含一堆缓存数据,路径名和存储在存储库中的文件的blob-ID(SHA-1)。

merge 成功后,一切都是“照常进行”,因此唯一的特殊情况是发生冲突的 merge 。当插槽1、2和/或3不为空时, merge 是“冲突的”。跳过大多数机制,会发生什么。 merge 对所有插槽都使用“最新”名称,并且:

  • 插槽零保留为空(除非您解决冲突,否则您不能“​​提交”,除非您确实要删除文件,否则该插槽将不再为空)。
  • 插槽1(“基本”)填充了公共(public)祖先版本。如果文件是新的(在两个修订版中),则此插槽为空。
  • 插槽2(“我们的”)中填充了目标版本(HEAD,除非您手动调用一些基础的 merge 机制)版本。如果在HEAD/merge 目标中删除了文件,则此插槽为空。
  • 插槽3(“它们的”)已被 merge 版本填充。如果在 merge 版本中删除了该文件,则该插槽为空。

  • 解决冲突并“git add”解决后,#0插槽将被您“添加”的内容填满,从#1到#3中清除条目;或者,如果您“git rm”有冲突的文件,则将另一个阶段条目仍被删除,但是现在#0插槽仍然为空,这也解决了冲突。

    然后,更具体地说,假设您有一个共同的祖先,(其中有)这两个文件:
    gronk
    flibby

    您位于 cleanup分支上,并且已将 gronk重命名为 breem,并对其和 flibby进行了编辑。您决定使用 git merge work,在那里他们修改了 gronk,但未重命名,并删除了 flibby。其他一些文件已干净 merge 。

    该索引将包含三个版本的 bleem和两个版本的 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查看 git show :1:bleem的原始(基本)版本。在基本版本中(在本例中,在本例中也称为 gronk)将其称为 work,但现在将其称为 bleem,因为git相信您在 gronk中将 bleem重命名为 cleanup。 (在这种情况下,Git会在merge-base和 HEAD之间找到重命名,然后在必要时对 work应用相同的重命名。)

    同样,您可以看到 work版本和 git show :3:bleemgit show work:gronk,以及 HEAD版本的任何一个: git show HEAD:bleemgit show cleanup:bleemgit show :2:bleem(插槽2包含 HEAD aka cleanup版本,并根据 HEAD中的名称进行命名)。

    但是,对于 flibby,由于已在 work中删除,因此没有“其”(插槽3)版本。

    要解决冲突,您只需要告诉 git addgit rm即可更新零槽条目并删除1至3条目。当然,使用 git add,进入插槽0的内容现在是工作目录中的内容,因此通常必须首先编辑文件。

    顺便说一句,我在上面的插槽2和3中标记了“我们的”和“他们的”。这也是 git checkout对待它们的方式( git checkout --oursgit checkout --theirs使您可以将版本2或3写入插槽0;这种 checkout (与大多数 checkout 一样)也“擦除”其他插槽,从而解决了冲突)。但是,在进行重新设置的过程中, HEAD分支实际上是要重新建立基础的分支,而“其”版本是您正在被重新建立基础的分支。因此,在我看来,我们(他们)的术语并不是那么好:在重新设置基准期间将其倒退是很容易的。

    我还应注意,如果您处于冲突 merge 的中间, git checkout -m将通过擦除插槽0并根据需要“恢复”插槽1-3中的版本来“重新创建” merge 冲突(并写入冲突的将文件 merge 到工作目录,同时也要遵守 merge.conflictstyle设置的所有更改)。

    关于git - git索引的内容在 merge 期间如何演变( merge 失败后索引中的内容)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21309490/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com