为什么我必须暂存文件才能让git意识到冲突已经解决了?

时间:2017-12-08 08:35:37

标签: git

问题:我改变多行,并且阶段+提交除了其中一个之外的所有行,然后我想推送提交。但是,在我推送它们之前,我想从另一个分支合并,看看是否还有一个冲突需要解决。

哦,哦,冲突!我修复了它,但为了让git同意它已修复,我来分阶段整个文件。 Noooo,我想保持这条单线不受限制。暂存整个文件会将这一行埋没在1000行冲突解决的更改中(因此找到它并取消暂存它将需要数天;-)。

为什么我不能告诉git“听,放松,忘记它,这不再是问题了,我想留下现在的样子 - 当我完成对单行的最后修复时我承诺我会将所有内容(最终;-)并提交给它。“

我错过了什么吗?是否有一个简单的工作流程可以解决这个问题?

干杯, 斯坦

2 个答案:

答案 0 :(得分:2)

可以通过补丁而不是整个文件来进行分段。使用git客户端或git add -p并仅放置您希望参与此提交的部分(可能是合并区域周围的部分)。

答案 1 :(得分:0)

您必须git add解决冲突的原因是冲突实际上存储在索引中,这与git add更新的位置相同。而且,不幸的是,这个存储会破坏您之前存储的经过仔细调整的版本。

描述

从根本上说,Git会在三个位置存储与当前和下一次提交有关的每个文件,而不仅仅是两个。

  • 作为HEAD提交的一部分,每个文件的副本都以Git的特殊Gitty格式(压缩等)存储,永久和只读。也就是说,如果.git/HEAD包含ref: refs/heads/branchX,那么您在分支branchX上,branchX表示"提交1234567...",那么哈希ID为1234567...的提交包含源树的完整快照。 (到目前为止没什么大不了的,这里没什么好吃的。)

  • 还有每个文件的副本,以纯文本格式存储 - 而不是一些特殊的Gitty变种 - 以便您可以在工作中编辑,编译和运行程序等等树。 (这里也没有什么值得惊讶的。)

  • 但在两者之间,每个文件都有一个第三个​​副本。第三个副本通常是,并且最初与HEAD提交副本相同。 (事实上​​,它采用特殊的Gitty格式,用散列ID替换实际文件。此外,该散列ID保存在普通数据文件.git/index中,以及一些缓存信息,所以它几乎不需要任何额外的空间:

    $ ls -l .git/index
    ...  300971 Dec  6 20:23 .git/index
    
    例如,

    表示Git的Git树的索引。)

当您在文件上运行git add时,您真正要做的就是将其复制回索引。运行git add <file>时,Git将<file>转换为特殊的Gitty格式 - 这是它实际进入存储库的时候! - 并将生成的哈希推送到索引中。如果你git add -p <file>并且最多但不是全部,那么最多但并非全部的版本现在都存储在索引中。

无论索引是什么,Git都会快照进入 next 提交。然后,新提交将接管当前提交&#34;,以便HEAD-即branchX - 现在意味着,例如,&#34;提交fedcba9...&#34 ;,这将是永久性和只读的,并包含文件的最终快照。 (同时,哈希1234567...现在被记住,因为它是存储在fedcba9...中的哈希。)

换句话说,在提交之后,索引再次匹配HEAD提交,因为HEAD提交是来自索引。一切都在零插槽中,不受干扰。

git merge如何破坏

这些索引条目中的每一个都是阶段零条目。对于没有冲突的条目,阶段0是正常阶段。但每个索引条目实际上最多有四个插槽。您可以在阶段0中拥有某些内容,或者通过删除阶段零条目 - 您可以在插槽1,2和/或3中使用某些内容。当git merge发现它必须合并文件时,它会就是这样:它消除了阶段零条目,将合并基础版本复制到阶段#1,将HEAD或--ours版本复制到阶段#2,并复制剩余的{{1版本到阶段#3。

Git将其留给低级文件合并处理程序来解决冲突,如果可以的话(如果你使用--theirs-X ours,它总是可以)。如果低级驱动程序确实解决了冲突,那么该驱动程序将-X theirs为您提供工作树副本。如果没有,它会将冲突留在工作树文件中,并保留三个非零阶段条目。

当您git add最终版本时,您告诉Git:删除第1到第3阶段,并将工作树中的任何内容放入第0阶段。(这即使git add也是如此。)

在执行此操作之前,git add -p无法提交,因为它只能提交存储在阶段0插槽中的条目。