我对git
索引的内容有些模糊的概念,因为我使用git-add
和git-commit
命令时会涉及到它,但是当执行git-merge
命令时,我并不知道这些内容会发生什么变化。特别是在合并失败(例如由于某些冲突)时,我想了解索引中保存的内容。
(实际上,一旦在索引中创建了一个条目,如果需要,它将用标志位 CE_REMOVED
标记。这变得非常复杂,因为整个目录中的文件都可以被标记为“已删除”,然后可以创建一个名称与前一个目录相同的文件,并标记为“已添加”。让我们假装我们有固定的空插槽。:-) )
插槽#0 是“正常的”,未冲突的,一切顺利的条目。它包含一堆缓存数据,路径名和存储在仓库中的文件的 blob-ID(SHA-1)。
当合并成功时,一切“照常”,所以唯一的特殊情况是冲突的合并。当 slot 1、2 和/或 3 不为空时,合并是“冲突的”。跳过大部分机制,发生的是这样的。合并使用“最新的”名称填充所有插槽,并且:
HEAD
,除非您手动调用某些底层合并机制)版本填充。如果文件已在 HEAD
/ 合并目标中被删除,则此插槽为空。gronk
flibby
你目前在分支cleanup
上,并且将gronk
重命名为breem
,并编辑了这两个文件以及flibby
。然后你决定执行git merge work
命令,合并来自工作区的修改,其中他们修改了gronk
但没有重命名它,并删除了flibby
。一些其他的文件已经成功合并。
索引中将包含三个版本的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
您可以使用git show :1:bleem
查看bleem
的原始(基本)版本。在基本版本中被称为gronk
(在此情况下也是work
中的名称),但现在被称为bleem
,因为Git认为您已将gronk
重命名为bleem
在cleanup
中。(Git在合并基础和HEAD
之间找到重命名,然后在必要时将相同的重命名应用于work
,就像在这种情况下一样。)git show :3:bleem
或git show work:gronk
查看work
版本,并使用任何以下选项查看HEAD
版本:git show HEAD:bleem
、git show cleanup:bleem
或git show :2:bleem
(插槽2包含HEAD
或cleanup
版本,并根据HEAD
中的名称进行命名)。flibby
,由于它在work
中被删除,因此没有“theirs”(插槽3)版本。git add
或git rm
更新插槽零条目并删除1至3条目。当然,使用git add
时,进入插槽0的内容是当前工作目录中的任何内容,因此通常需要先编辑文件。顺便提一下,我在上面标签2和3为“ours”和“theirs”。这也是git checkout
的处理方式(git checkout --ours
和 git checkout --theirs
让您将版本2或3写入插槽0;像大多数检出操作一样,“删除”其他插槽,从而解决冲突)。但是,在一个变基中,HEAD
分支实际上是正在进行变基的分支,“theirs”版本是您正在变基的分支。因此,在我看来,ours/theirs术语并不是很好:在变基期间很容易混淆。
我还要注意的是,如果您处于冲突的合并中,git checkout -m
将通过擦除插槽0并根据需要“复原”插槽1-3中的版本(并将冲突合并文件写入工作目录,同时遵循您的merge.conflictstyle
设置中的任何更改),“重新创建”合并冲突。
git rebase -i
命令,将所有的pick
替换为edit
,然后观察 .git 修改来看看发生了什么。 - Asenarrebase
在内部是一系列的cherry-pick
操作,对于每个被cherry-pick
的提交,Git使用合并机制来应用该提交所暗示的更改。 - torek