【问题标题】:git revert HEAD~2 creates a conflict with no appropriate resolutiongit revert HEAD~2 造成没有适当解决方案的冲突
【发布时间】:2014-02-09 23:20:42
【问题描述】:

假设我们有四个提交(D 是头部)

A-B-C-D

如果我想删除(恢复)提交 B 中的更改,但保留 C 和 D 中所做的更改,你会怎么做?

如果我这样做

git revert HEAD~2

我遇到了冲突。选择分辨率时,仅有的两个选项是使用在 A 中所做的更改,或者保持原样(在 D 中所做的更改)。

例如。

提交A后,文本文件包含

commit 1

在提交 B 之后,它包含

commit 1
commit 2

在提交 C 之后,它包含

commit 1
commit 2
commit 3

在提交 D 之后,它包含

commit 1
commit 2
commit 3
commit 4

所以如果我现在做git revert HEAD~2,我最终应该得到包含

的文本文件
commit 1
commit 3
commit 4

对吗?如果不是,您能否解释一下原因,因为这正是在 Mercurial 上恢复时发生的情况。

编辑:没有重写历史记录。

【问题讨论】:

  • 我会在这里使用git rebase
  • 比较 HEAD~2 添加的内容与您最终更改的内容之间的差异。这不再是一个微不足道的反向应用补丁了
  • @raina77ow 我基本上需要撤消提交 B 中的更改。如何使用 git rebase 来完成?
  • @zapl 我现在明白了。 Mercurial 产生正确的输出(显示在最后一个代码块中) - 仅撤消提交 B 中的更改的等效 git 命令是什么?
  • 嗯,我会开始手动修复它,因为我不知道,寻找更好的解决方案通常需要更长的时间 :) stackoverflow.com/questions/17962955/…

标签: git


【解决方案1】:

好的,让我们通过 git 进行实际会话,这样我们就可以确定我们都在谈论同一件事。我们从新目录中的新仓库开始:

$ mkdir /tmp/temprepo; cd /tmp/temprepo
$ git init
Initialized empty Git repository in /tmp/temprepo/.git/
$ echo 'commit 1' > file.txt
$ git add file.txt
$ git commit -m commit-A
[master (root-commit) 1898863] commit-A
 1 file changed, 1 insertion(+)
 create mode 100644 file.txt
$ echo 'commit 2' >> file.txt; git commit -a -m 'commit-B'
[master 1d77fa5] commit-B
 1 file changed, 1 insertion(+)
$ echo 'commit 3' >> file.txt; git commit -a -m 'commit-C'
[master 0bf2ede] commit-C
 1 file changed, 1 insertion(+)
$ echo 'commit 4' >> file.txt; git commit -a -m 'commit-D'
[master 9980dfd] commit-D
 1 file changed, 1 insertion(+)
$ git revert HEAD~2
error: could not revert 1d77fa5... commit-B
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'

让我们看看失败的revert,看看git认为问题出在哪里。请注意,我将 merge.conflictstyle 设置为 diff3 以便在三向合并失败时查看基本版本中的内容:

$ git config --get merge.conflictstyle
diff3
$ cat file.txt
commit 1
<<<<<<< HEAD
commit 2
commit 3
commit 4
||||||| 1d77fa5... commit-B
commit 2
=======
>>>>>>> parent of 1d77fa5... commit-B

这就是为什么 git 需要你,用户帮助的原因:“基本版本”——commit-A 中的版本——有一行,commit 1,然后结束。 “要删除的更改”是在commit 1 之后添加一行,但在文件末尾,包含commit 2HEAD 中的“当前”版本有四行,commit 1commit 2commit 3commit 4

因此,Git 无法删除 last 行 (commit 4),该行与要删除的行不匹配;也不能简单地删除行commit 2,因为在那之后文件并没有结束。

您现在应该做的是自己修复文件,在某些编辑器中创建“删除更改的版本”,然后是 git add file.txtgit revert --continue

顺便说一句,让我们在 Mercurial 中执行相同的序列:

$ cd ..
$ rm -rf temprepo/
$ mkdir temprepo
$ cd temprepo
$ hg init
$ echo 'commit 1' > file.txt
$ hg add file.txt
$ hg commit -m commit-A
$ echo 'commit 2' >> file.txt
$ hg commit -m commit-B
$ echo 'commit 3' >> file.txt
$ hg commit -m commit-C
$ echo 'commit 4' >> file.txt
$ hg commit -m commit-D
$ hg backout -r 1
reverting file.txt
merging file.txt
warning: conflicts during merge.
merging file.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges
$ cat file.txt
commit 1
<<<<<<< local
=======
commit 2
commit 3
commit 4
>>>>>>> other

换句话说,Mercurial 的行为与 git 相同:它无法在没有帮助的情况下撤消“commit-B”。

【讨论】:

  • “文件末尾”是锦上添花。谢谢。
  • @OpenderSingh:是的,一般的想法是 git(或 hg,或任何其他应用补丁的命令,例如,patch :-))尝试匹配“上下文”行以及变化。不过,文件开头或文件结尾也算作一种上下文行。
猜你喜欢
  • 2021-04-10
  • 2014-07-14
  • 2015-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
  • 2015-08-23
相关资源
最近更新 更多