假设我们有四个提交(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时发生的事情。
修改:无重写历史记录。
答案 0 :(得分: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'
让我们来看看失败的恢复,看看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 2
。 HEAD
中的“当前”版本有四行,commit 1
,commit 2
,commit 3
和commit 4
。
commit 4
),该行与要删除的行不匹配;也不能简单地删除行commit 2
,因为文件之后没有结束。
您现在应该做的是在一些编辑器中自行修复文件,以创建“删除更改的版本”,然后git add file.txt
和git 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”。