当 Git 合并由于冲突或用户使用选项请求而停止时--no-commit,合并被认为仍在进行中,这通过文件的存在来指示$GIT_DIR/MERGE_HEAD。
当提交合并结果或中止合并时,此状态通常结束。在后一种情况下,合并引入的更改将被回滚。
有没有什么方法可以完成“合并正在进行”状态而不生成提交并且不会丢失合并中的更改?让我们假设所有可能的冲突都已解决。1这类似于为--quit挑选、恢复和变基提供的选项。
一个明显的方法是git reset --soft,但是当合并正在进行时,这个错误就会出现。
对于这个问题,我没有任何具体的用例,但我想知道 Git UI 在这一点上的完整性。
1从 torek 非常详细的回答中可以看出,未解决的冲突意味着索引槽 1 到 3 中的条目,这些条目仅在正在进行的合并期间才有意义,严格来说甚至构成一个。这意味着:只要存在未解决的冲突,合并就会持续进行。因此,为了使这个问题反映一个适定的问题,它必须限于所有可能的冲突都得到解决的情况。
使用 Git 2.23(2019 年第 3 季度),这将更容易(不再git reset),因为“git merge学习”--quit选项可以清理正在进行的合并,同时使工作树和索引仍然混乱。
请参阅提交 f3f8311(2019 年 5 月 18 日)和提交 b643355(2019 年 5 月 09 日),作者:Nguy\xe1\xbb\x85n Th\xc3\xa1i Ng\xe1\xbb\x8dc Duy ( pclouds)。
\n (由Junio C Hamano 合并 -- gitster--在提交 c4a38d1中,2019 年 6 月 13 日)
\n\n\n\n\n
merge: 添加--quit这允许取消当前合并而不重置工作树/索引,这就是 --abort 的用途。
\n\n
\n 与其他--quit(s)一样,当您忘记自己正处于合并过程中并且已经切换出去,做不同的事情时,通常会使用此方法。
\n 当您意识到时,您甚至无法再继续合并了。这也使得所有正在进行的命令 、
\nam、merge和rebase\revertncherry-pick都采用全部三个--abort,--continueand--quit(bisect具有不同的 UI)。
该文档位于Phillip Wood ( )的提交 437591a(2019 年 6 月 17 日)中。\n (由Junio C Hamano 合并 -- --在提交 0af6d5d,2019 年 7 月 09 日)phillipwoodgitster
\n\n忘记当前正在进行的合并。
\n
\n 保持索引和工作树不变。
你主要要做的git reset是重置--mixed。这确实会丢失一些信息,这意味着答案是否定的。如果没有任何冲突需要解决,您可以执行git add -u或git add .类似操作来恢复丢失的信息;但无论如何,为了使这个答案有意义,这里还需要注意一些额外的事情。
首先,Git 根本没有真正使用你的工作树。可以肯定的是,它确实将文件放入您的工作树中,并且会在各种条件下检查它们的更改\xe2\x80\x94是否与索引\ xe2\x80\x94中的内容存在差异,例如git add -u,或在破坏工作之前-tree 文件由于另一个git checkout. 当然,以git merge熟悉的形式将合并冲突写入工作树文件中:
$ cat file\nsome contents\na few lines\nof contents just\n<<<<<<< HEAD\nto make some\n||||||| merged common ancestors\nto make \n=======\nto make\n>>>>>>> branch\nthings more\ninteresting\nRun Code Online (Sandbox Code Playgroud)\n\n(这是merge.conflictStyle设置为diff3, 添加该||||||| merged common ancestors部分,以便您可以看到合并冲突发生之前存在的内容 \xe2\x80\x94 在这种情况下,之前存在的内容是尾随空格,我通过删除它来修复branch它,但是在master通过添加更多单词)。
不过,我上面提到的索引才是真正的行动所在。这个东西\xe2\x80\x94这个索引,Git也将其称为暂存区或缓存,具体取决于Git的谁/哪个部分正在执行调用\xe2\x80\x94包含文件的版本这将进入下一次提交。
\n\n与工作树一样,索引纯粹是临时的。但从某种意义上来说,它对 Git 来说比工作树更重要。您可以创建一个--bare存储库;这样的存储库没有工作树,但它仍然有提交,并且仍然有索引。1 Git 可以将提交读入索引,并从索引写入新的提交,所有这些都不需要工作树。
在正常情况下,索引中的内容非常简单。Git 中的每次提交都会保存每个文件的完整副本。它将该文件保存为一种特殊的、只读的、压缩的、仅限 Git 的形式。我喜欢称这些文件为“冻干”。每个这样的文件都有一个唯一的 blob hash\xe2\x80\x94,对于文件的内容来说是唯一的。索引中的正是这些相同的冻干文件,或更准确地说,是 blob 哈希值。提交中的文件与索引中的文件之间的主要区别在于,索引中的文件可以用新的、不同的冻干文件(不同的 blob 哈希)覆盖。好吧,您可以添加新文件,或删除现有文件,一切都以这种冻干形式进行。
\n\n无论如何,在 Git 中进行新提交的动作非常快,因为它实际上所做的就是获取索引中已有的所有冻干文件,并在提交中记录它们的 blob 哈希值(通过更多称为树的 Git 对象)但这只是一个实现细节)。新的提交获得一个新的、唯一的哈希ID;新的提交会记住之前当前提交的哈希 ID;HEAD然后,通过将哈希 ID 写入或写入分支名称,新提交将成为当前提交,并且如果您位于分支上,则成为当前分支的头部。
因此,在正常使用中,在非裸存储库中,每个文件始终有三个活动副本。如果您有一个名为 的文件README.md,那么您实际上有:
HEAD:README.md:这是当前提交中的冻结副本。你不能改变它,Git 也不能。(您可以移动HEAD到另一个提交,但这不会影响此提交README.md。):README.md:这是索引中的副本。它是冻干格式的,但您可以随时用新副本替换它。README.md:这是您可以看到、尝到和闻到的唯一文件\xe2\x80\x94 或您对计算机上的文件执行的任何操作。它不是冻干形式。它位于您的工作树中,因此您可以对任何其他文件执行所有操作。一次影响这三个文件的主要命令\xe2\x80\x94忽略一次git checkout <branch>影响多个\xe2\x80\x94的明显的命令和类似命令是:
git checkout [commit] [--] paths:从某些提交中获取单个文件,将它们复制到索引中,然后复制到工作树中。git reset [commit] [--] paths:将某个提交中的单个文件复制到索引,而不触及工作树。git add [--] paths:将单个文件从工作树复制到索引,并在复制过程中将它们冻干。然而,当您开始合并时,索引将扮演一个新的、扩大的角色。索引中的每个文件现在不再只有一个副本,而是最多三个副本。file上例中的三个副本是:
:1:file:这是来自合并基础提交的文件,工作树冲突文件中提到的合并共同祖先。:2:file:这是来自提交的文件HEAD。:3:file:这是来自其他提交的文件,在本例中是branch.:0:file目前没有\xe2\x80\x94这个名字:file缩写为:0:file\xe2\x80\x94,因为有这三个非零阶段编号的文件。
当您最终解决所有冲突并运行or时,git merge需要进行合并提交的另一件事是另一个提交的原始哈希 ID。所以 Git 已将其保存到( ,如您所提到的)中的文件中。因此,正在进行合并的事实记录在两个位置:此文件以及存在未合并的索引条目的事实。git commitgit merge --continue.git.git/MERGE_HEAD.git/MERGE_HEAD
要停止合并,必须将所有索引条目放回阶段零。这意味着您必须选择一些文件从阶段 1、2 和/或 3 移至阶段 0,或使用工作树副本(通过git add)放入阶段 0,或使用HEAD副本放入阶段零。
现在,如果它们已经全部处于第 0 阶段,或者是因为您已经解决了所有冲突,或者因为您没有冲突并且只是用于git merge --no-commit进入此状态,那么这会产生一个相当糟糕的副作用:git reset --mixed将提交读HEAD入索引,这样您就会丢失所有已添加的、已解决的冲突。但是那些添加的已解决的冲突现在也在您的工作树中,因此您(可能)可以将它们放回去(但请参阅脚注之前的最后一段)。
根据定义,任何不在阶段零的条目都意味着存在正在进行的未解决的合并。如果不破坏一些正在进行的未解决的合并,就无法解决这个问题。
\n\n具有git reset --mixed删除 的额外副作用.git/MERGE_HEAD,因此不再有正在进行的合并。这样就解决了另一个问题。最重要的是如何处理高级索引条目,而这个特定问题只能通过销毁信息来解决。无论您是否打算保留这些信息,都必须这样做。
如果出于某种原因,您巧妙地暂存了file既不在HEAD提交也不在工作树中的某个版本,这git reset --mixed将破坏其哈希值。因此,您可能想要git checkout-index将其提取到某个临时文件中,或者至少记录其 blob 哈希值并用于git update-index --index-info恢复它。但除此之外,答案主要是git reset。
1实际上,它可能也不应该有索引。毕竟,当您将工作树添加到非裸存储库时,您实际上同时添加了索引和工作树。但是 Git 的一些内部部分坚持,或者曾经坚持,锁定索引,所以它必须有一个索引来锁定。
\n| 归档时间: |
|
| 查看次数: |
5437 次 |
| 最近记录: |