git索引的内容在合并期间如何演变(合并失败后索引中的内容)? [英] How do contents of git index evolve during a merge (and what's in the index after a failed merge)?

查看:99
本文介绍了git索引的内容在合并期间如何演变(合并失败后索引中的内容)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对git索引所包含的内容与git-add s和git-commit s所包含的内容一模一样,但我不知道当执行git-merge时这些内容会如何.我特别想了解合并失败(例如由于某些冲突)时索引的内容.

I have a fuzzy idea of what the git index contains as one does git-adds and git-commits, but I don't have a clue of what happens to these contents when one does a git-merge. I'm particularly interested in learning what the index holds when a merge fails (e.g. due to some conflict).

推荐答案

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

For any given path, there are up to four "version numbers" in the index, numbered 0 (zero) through 3. I'll call them "slots" as if they were actually there for every entry, and then easily indexed (this makes them easier to think about), although actually extra versions are introduced dynamically only when needed. These "virtual slots" can be "empty", meaning the file does not exist.

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

(Actually, once an entry is created in the index, it's marked with a flag bit, CE_REMOVED, if needed. This gets hairy because a whole directory full of files can be marked "removed" and then a file can be created with the name of the previous directory and marked "added". Let's just pretend we have fixed slots, there-but-empty, instead. :-) )

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

Slot #0 is the "normal", un-conflicted, all-is-well entry. It contains a bunch of cache data, the path name, and the blob-ID (the SHA-1) for the file stored in the repository.

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

When a merge succeeds, it's all "business as usual", so the only special case is a conflicted merge. A merge is "conflicted" when slots 1, 2, and/or 3 are non-empty. Skipping over most of the mechanics, what happens is this. The merge uses the "newest" name for all the slots, and:

  • 插槽零保留为空(除非您解决冲突,否则您不能​​提交",到那时该插槽将不再为空,除非您确实要删除文件).
  • 插槽1(基本")已填充有通用祖先版本.如果文件是新文件(在两个版本中都是新文件),则此插槽为空.
  • 插槽2(我们的")中填充了目标版本(HEAD,除非您手动调用某些基础的合并机制)版本.如果在HEAD/合并目标中删除了文件,则此插槽为空.
  • 插槽3(它们的")已被合并的版本填充.如果在合并版本中删除了该文件,则该插槽为空.
  • Slot zero is left empty (you can't "commit" until you resolve the conflict, by which time this slot won't be empty anymore unless you really want the file to be removed).
  • Slot 1 ("base") is filled with the common ancestor version. If the file is new (in both revisions), this slot is empty.
  • Slot 2 ("ours") is filled with the target (HEAD, unless you're manually invoking some of the underlying merge machinery) version. If the file was removed in HEAD / target-of-merge, this slot is empty instead.
  • Slot 3 ("theirs") is filled with the being-merged-in version. If the file was removed in the being-merged-in revision, this slot is empty.

一旦解决冲突并"git add",#0插槽就会被您添加"的内容填满,从而清除#1到#3中的条目,或者,如果您"git rm"冲突的文件,其他阶段的条目仍被删除,但是现在#0插槽仍然为空,这也解决了冲突.

Once you resolve the conflict and "git add", the #0 slot gets filled in with whatever you "add", wiping out the entries in #1 through #3—or, if you "git rm" the conflicted file, the other stage entries are still removed, but now the #0 slot remains empty, which also resolves the conflict.

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

More concretely, then, suppose you have a common ancestor that has (among others) these two files:

gronk
flibby

您在分支cleanup上,并且已将gronk重命名为breem,并对其和flibby进行了编辑.您决定使用git merge work,在此他们修改了gronk但未重命名并删除了flibby.其他文件完全合并.

You're on branch cleanup and you've renamed gronk to breem, and edited both that and flibby. You decide to git merge work, where they modified gronk but did not rename it, and removed flibby. Some other file(s) merged cleanly.

索引将包含三个版本的bleem和两个版本的flibby:

The index will contain three versions of bleem and two versions of 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

您可以在git show :1:bleem中看到bleem的原始(基本)版本.在基本版本中(在本例中,在此情况下也在work中)将其称为gronk,但是现在它被称为bleem,因为git相信您在cleanup中将gronk重命名为bleem. (在这种情况下,Git会在merge-base和HEAD之间找到重命名,然后根据需要对work进行相同的重命名.)

You can see the original (base) version of bleem with git show :1:bleem. That was called gronk in the base version (and in work as well, in this case), but now it's called bleem because git believes you renamed gronk to bleem in cleanup. (Git finds the renames between the merge-base and HEAD and then applies the same renaming to work if necessary, as in this case.)

同样,您可以看到带有git show :3:bleemgit show work:gronkwork版本以及带有git show HEAD:bleemgit show cleanup:bleemgit show :2:bleemHEAD版本(插槽2包含HEAD aka cleanup版本,并根据HEAD中的名称进行命名.)

Likewise, you can see the work version with git show :3:bleem or git show work:gronk, and the HEAD version with any of: git show HEAD:bleem, git show cleanup:bleem, or git show :2:bleem (slot 2 contains the HEAD aka cleanup version, and is named according to the name in HEAD).

对于flibby,由于在work中已将其删除,因此没有其"(插槽3)版本.

For flibby, though, since it was removed in work, there is no "theirs" (slot 3) version.

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

To resolve the conflicts, you need only tell git add or git rm to update the slot-zero entry and remove the 1-through-3 entries. Of course, with git add, what goes into slot 0 is whatever is in the work directory now, so you generally have to edit the files first.

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

Incidentally, I labeled slots 2 and 3 "ours" and "theirs" above. This is how git checkout treats them as well (git checkout --ours and git checkout --theirs let you write version 2 or 3 into slot 0; such a checkout, like most checkouts, "erases" the other slots too, thus resolving the conflict). However, in a rebase, the HEAD branch is actually the branch being rebased-on-to, and the "theirs" version is your branch-being-rebased. So the ours/theirs terminology is not really that great, in my opinion: it's too easy to get it backwards during a rebase.

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

I should also note that git checkout -m will "re-create" a merge conflict, if you're in the middle of a conflicted merge, by erasing slot 0 and "resurrecting" the versions in slots 1-3 as needed (and writing the conflicted merge file to the working directory, obeying any change in your merge.conflictstyle setting as well).

这篇关于git索引的内容在合并期间如何演变(合并失败后索引中的内容)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆