git revert : 即使在简单的情况下也无法撤消单个提交
git revert : Unable to undo an individual commit even in a simple case
为了尝试理解 git revert
,我对一个文本文件 foo.txt
进行了一系列 4 次简单提交——A、B、C、D——稍后仅撤消提交 B 并完整保留提交 A、C、D。
因此,在每次提交中,我都在文件中添加了一个新行,模拟添加的功能或引入的错误。
提交A后,foo.txt
的内容:
Feature A
提交B后,foo.txt
的内容: (这里,我引入一个错误,我稍后会尝试undo/revert.)
Feature A
Bug
提交C后,foo.txt
的内容:
Feature A
Bug
Feature C
提交D后,foo.txt
的内容:
Feature A
Bug
Feature C
Feature D
现在,要撤消提交 B(引入错误)的影响,我做了:
git revert master^^
我期望发生的是,一个新的 Commit 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 的 hash,'Bug introduced' 这个 commit 的评论。)
问题:
这是怎么回事?
如果连这么简单的一行提交都不能reverted/undone自动完成,必须要我手动解决,那我怎么能还原一个更复杂的提交,其原始开发者甚至可能是别人!
是否有一组特殊情况下 git revert
更适用?
git
将每个提交视为一个更改列表(我在这里简化了事情)并尝试 "unapply" 当您调用 git revert
时。每个更改列表还包括一些上下文以确保更改有意义。例如,如果我们要进行的更改是 "add return
after line 10",那么它比 "add return
after line 10, if lines 7-9 contain X, Y, and Z" 更有可能破坏事物。因此,我们可以将您的第二次提交描述为(再次在这里稍微简化一下):
- 假设文件的第一行是
Feature A
.
- 假设没有第二行
- 让第二行包含
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,必须有一些上下文,因为我们不能简单地将 some_value = 123
替换为旧行 read_int_into(some_vlue)
- 这将是编译错误。
为了尝试理解 git revert
,我对一个文本文件 foo.txt
进行了一系列 4 次简单提交——A、B、C、D——稍后仅撤消提交 B 并完整保留提交 A、C、D。
因此,在每次提交中,我都在文件中添加了一个新行,模拟添加的功能或引入的错误。
提交A后,foo.txt
的内容:
Feature A
提交B后,foo.txt
的内容: (这里,我引入一个错误,我稍后会尝试undo/revert.)
Feature A
Bug
提交C后,foo.txt
的内容:
Feature A
Bug
Feature C
提交D后,foo.txt
的内容:
Feature A
Bug
Feature C
Feature D
现在,要撤消提交 B(引入错误)的影响,我做了:
git revert master^^
我期望发生的是,一个新的 Commit 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 的 hash,'Bug introduced' 这个 commit 的评论。)
问题:
这是怎么回事?
如果连这么简单的一行提交都不能reverted/undone自动完成,必须要我手动解决,那我怎么能还原一个更复杂的提交,其原始开发者甚至可能是别人!
是否有一组特殊情况下
git revert
更适用?
git
将每个提交视为一个更改列表(我在这里简化了事情)并尝试 "unapply" 当您调用 git revert
时。每个更改列表还包括一些上下文以确保更改有意义。例如,如果我们要进行的更改是 "add return
after line 10",那么它比 "add return
after line 10, if lines 7-9 contain X, Y, and Z" 更有可能破坏事物。因此,我们可以将您的第二次提交描述为(再次在这里稍微简化一下):
- 假设文件的第一行是
Feature A
. - 假设没有第二行
- 让第二行包含
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,必须有一些上下文,因为我们不能简单地将 some_value = 123
替换为旧行 read_int_into(some_vlue)
- 这将是编译错误。