Git恢复命令错误

时间:2014-05-08 08:57:08

标签: git git-revert

当我恢复git存储库中的特定提交时,它会出现以下错误:

Command for reverting is  **git revert <commit-hash>**

error: Commit <commit-hash> is a merge but no -m option was given.
fatal: revert failed

任何人都可以解释为什么会出现这个错误吗?

-Thanks 克里希纳

2 个答案:

答案 0 :(得分:4)

只需阅读罚款manpage: - ):

  

通常您无法恢复合并,因为您不知道哪一方   合并应该被视为主线。此选项指定父编号   (从1开始)主线并允许恢复相反的变化   指定的父级。

     

[...]

     

恢复合并提交声明您永远不会想要树   合并带来的变化。因此,以后的合并只会   引入不是祖先的提交所引入的树更改   先前恢复的合并。这可能是也可能不是你想要的。

问题在于合并提交比常规提交更复杂 - 它不仅更改文件,还将两个分支链接在一起。还原它时,您必须决定(并告诉git)您是否只想回滚它引入的文件更改,或者还要链接分支。

  • 如果您要回滚更改,但保持分支的链接,请使用选项-mgit merge,如联机帮助页中所述。
  • 如果要完全撤消合并,则必须使用the complications that can bring重写历史记录(使用git rebasegit resetgit cherry-pick的组合)。

您需要什么取决于您恢复提交的原因。

答案 1 :(得分:3)

git revert至&#34;退出&#34;一个变化,它需要弄清楚变化是什么。

在大多数普通提交的情况下,更改很容易计算。考虑一下这个git commit graph fragment:

... - G - H ...    <-- HEAD=master

此处您已经提交了masterG,然后还有更多提交的分支H

如果你要求git恢复提交H,它只需要查看修订版G&#34;中的所有内容之间发生了什么变化。和#34;修订版H&#34;中的所有内容。通过比较GH

,Git可以通过相同的方式执行此操作
$ git diff <sha1-of-G> <sha1-of-H>

如果这表示在提交H中,您向文件readme.txt添加了一行并完全删除了文件x.h,那么git可以通过从{{1从提交readme.txt恢复文件x.h

但是,合并提交更复杂。让我们填写一些提交图:

G

如果你要求git恢复合并提交 I - J / \ ... - G - H M - N - O <-- HEAD=master \ / K - L ,应该退出哪些更改?

MJ的一系列变化:

M

(事实上,与提交$ git diff <sha1-of-J> <sha1-of-M> 相比,这些更改通过提交L带来的更改,这将是提交HK的更改组合)。

LL还有另一种可能完全不同的变化:

M

(这些更改实际上是$ git diff <sha1-of-L> <sha1-of-M> I中的更改,类似的逻辑)。

你必须告诉git 哪些更改要撤消,要保留哪些。 Git通过指定&#34;主线&#34;来完成此操作。这还依赖于以下事实:合并提交中存储的父ID是按特定顺序

当您进行合并时,我们假设您处于提交J,即J

master

现在您处于提交$ git checkout master # i.e., commit J $ git merge branch # i.e., commit L ,仍然是O。分支名称master可能不再存在(或者可能指向branch以外的某些提交),但您要放弃LK中的更改 - 即,当您进行合并时,在分支L上的那些。

branch第一个父级是M,因为您已将J合并到branch中,通过制作master来进行git记录第一个父级和J第二个父级。因此,要放弃提交LK的更改,您现在可以使用:

L

(此处$ git revert -m 1 HEAD~2 备份两次提交,从HEAD~2O再到N)。然后,Git可以MM^1)对J进行区分,M找到通过合并分支branch引入的更改,如上所述;然后撤消这些更改会导致退出合并引入的更改。

请注意,这会进行新的提交,从而产生如下图:

              I - J
            /       \
... - G - H           M - N - O - P   <-- HEAD=master
            \       /
              K - L

比较提交OP产生与比较MJ基本相同的事情(按顺序,即&#34;正常&#34;从JM进行比较。然而,就git的后续操作而言,您可能通过手工编辑O的树并进行新的提交P来完成此操作:它不会记录(除了提交消息文本)P基本上是对KL的回复。


顺便提一下,值得注意的是,在这种特殊情况下,您可以先简单地还原L,然后还原K,以(可能)获得相同的效果(另外两个额外的效果)提交):

$ L=$(git rev-parse HEAD~2^2)   # get sha-1 ID of commit L
$ git revert $L                 # make new commit P that reverts L
$ git revert $L^                # make new commit Q that reverts L^ = K
然而,通过大合并,恢复每个人的改变是很多工作;恢复合并提交本身要容易得多(要做到这一点,以及稍后理解,如果记录得当)。 (另外,&#34;可能&#34;上面是因为合并处理在&#34;分支的两侧&#34;上进行的相同更改,并且还原合并避免撤消K和{中的更改{em> not
的{1}}被带到L,因为他们发生在M和/或I。但是,这有点罕见,特别是在像这样的小分支结构中。)