问题:我改变多行,并且阶段+提交除了其中一个之外的所有行,然后我想推送提交。但是,在我推送它们之前,我想从另一个分支合并,看看是否还有一个冲突需要解决。
哦,哦,冲突!我修复了它,但为了让git同意它已修复,我有来分阶段整个文件。 Noooo,我想保持这条单线不受限制。暂存整个文件会将这一行埋没在1000行冲突解决的更改中(因此找到它并取消暂存它将需要数天;-)。为什么我不能告诉git“听,放松,忘记它,这不再是问题了,我想留下现在的样子 - 当我完成对单行的最后修复时我承诺我会将所有内容(最终;-)并提交给它。“
我错过了什么吗?是否有一个简单的工作流程可以解决这个问题?
干杯, 斯坦
答案 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插槽中的条目。