git revert:即使在一个简单的情况下也无法撤消单个提交

git revert:即使在一个简单的情况下也无法撤消单个提交

问题描述:

为了尝试和了解git revert,我对文本文件做了一系列4个简单的提交--A,B,C,D - foo.txt目的是稍后撤销提交B并保持提交A,C,D完好无损。git revert:即使在一个简单的情况下也无法撤消单个提交

因此,在每次提交时,我都在文件中添加了一行,模拟添加的功能或引入的错误。

提交后A,中foo.txt内容:

Feature A 

提交B之后,中foo.txt内容:(在这里,我介绍一下,我会稍后再试撤消/复原的错误。 )

Feature A 
Bug 

提交后的C,foo.txt内容:

Feature A 
Bug 
Feature C 

提交后d的foo.txt内容:

Feature A 
Bug 
Feature C 
Feature D 

现在,撤消提交B的影响(其推出的bug),我所做的:

git revert master^^ 

我想要发生的是,一个新的提交E从文件中删除Bug行,将文件保留经济需求为:

Feature A 
Feature C 
Feature D 

但是,我得到了错误:

error: could not revert bb58ed3... Bug introduced 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 

与文件的下列不成功git revert存在的内容:

Feature A 
<<<<<<< HEAD 
Bug 
Feature C 
Feature D 
======= 
>>>>>>> parent of bb58ed3... Bug introduced 

bb58ed3是哈希Commit B,'Bug介绍'此提交的评论。)

问:

  1. 这到底是怎么回事?

  2. 如果即使这样一个简单的单行提交不能自动恢复/撤消,并且必须要求我手动解析,那么我怎么能恢复一个更复杂的提交,其原始开发人员甚至可能是别人!

  3. 是否有一组特殊情况下git revert会更好适用?

git看到每个提交的修改列表(我这里简单化的东西),并试图“不应用”,当你调用git revert。每个更改列表还包含一些上下文以确保更改有意义。例如,如果我们想做出改变是“行之后添加return 10”,它更可能打破东西比“添加return线10后,如果行7-9含有X,Y和Z”。因此,我们可以描述你的第二次提交(再次,简化这一点):

  1. 假设文件的第一行是Feature A
  2. 假设没有第二线。
  3. 使第二行包含Bug

您添加后几行中,Bug的情况下显著变化,所以git revert是不知道这是否可以简单地将其清除。也许新添加的行实际上修复了错误。所以它要求你明确地解决上下文的冲突。

至于你的问题2-3:是的,git revert是可用的情况下,当你恢复了一块文件的哪个从那时起没有改变。例如,该错误在foo函数被引入,但此后仅bar函数(它位于下面十条线)作了修改。在这种情况下,git revert很可能会自动恢复更改,因为它认为上下文未更改。

UPD:这里就是为什么即使背景下,如果你想恢复自己的代码中重要的一个例子:

提交A(介意输入错误):

int some_vlue = 0; 
read_int_into(some_vlue); 
some_vlue = some_vlue++; 

提交B(错误引入的):

int some_vlue = 0; 
some_vlue = 123; 
some_vlue = some_vlue++; 

提交C(固定名称):

int some_value = 0; 
some_value = 123; 
some_value = some_value++; 

现在,为了恢复提交B,必须有一些上下文,因为我们不能简单地用旧行read_int_into(some_vlue)来代替some_value = 123 - 这将是编译错误。

+0

我认为,上下文的是伤害比帮助更多。 'git'应该允许通过'git revert'选项禁用上下文的使用。当您发送补丁并盲目应用补丁或者不知道补丁是否应用于正确的目标及其版本时,上下文会很有用。但在像我这样的情况下,'git'本身准确地知道确切的源和目标,所以为什么要使用上下文,我想知道!欣赏你的解释,顺便说一句。在最后标记之前,我会再等一等。 – Harry

+1

@哈里我已经添加了一些解释。使用变量重命名和方法重命名可能会出现更复杂的情况,并且在某些情况下,最终的代码甚至可以编译。所以,不可能自动检查我们是否可以忽略上下文,'git'是否安全。 – yeputons

+0

你的例子绝对有道理。但是,那么'git'怎么可能依赖(有限的)上下文,因为重命名可以在上下文之外发生? – Harry