git - 您能否在不造成冲突的情况下恢复除最后一次提交以外的提交?

标签 git git-revert

假设我只有一个分支,我的提交历史是:

A - B - C - D

如果我在 GUI(如 GitKraken 或 Windows 版 Git)中单击 C 并执行“还原提交”,我会收到一条文件冲突消息。

两个问题:

  1. 这是因为还原“撤消”了在 C 和 GIT 中所做的更改吗 现在卡在 B 和 D 中,它们以不同的方式修改文件, 不兼容的方式?是这个原因吗?

  2. 如果是,这是否意味着您只能还原最后一个 犯罪?除了最后一次,你能恢复提交吗? 不产生冲突?

更新

在@RomainValeri 提供非常有用的说明后编辑问题。我想我在恢复和重置之间混淆了太多。在他下面的例子中,做

git revert B

导致分支从

A-B-C-D

A-B-C-D-E

如果 B 是唯一更改了 file2.txt 的提交,并且 B 没有对其他文件进行任何其他更改,那么在还原之后创建的新提交 E 将保留 C 和 D 中所做的所有更改但不是 B 制造的。这是正确的吗?

这是因为,从技术上讲,恢复意味着取消、撤消提交的任何更改 - 这是正确的吗?

另外:假设我的工作目录中只有一个文件。如果 B 是唯一更改我文件中函数 fun1() 的提交,而所有其他提交更改同一文件中的其他函数,那么还原 B 很可能会导致冲突 ,因为 git 根据文件中的行来思考,而不是根据文件中的函数来思考。这是正确的吗?

假设 B 更改了 fun1(),C 更改了 fun2(),D 更改了 fun3()。然后我意识到在 B 处在 fun1() 中所做的更改是错误的,我需要撤消它们。 如果所有这些函数都在同一个文件中,有没有办法撤消 B 中的更改,同时保留 C 和 D 中的更改?

相反,如果这 3 个函数中的每一个都在一个单独的文件中,那么在不影响其他提交的情况下撤消一个提交的更改会简单得多,对吗?

我想这当然是为什么单个文件永远不能太大,也不能包含太多函数来做不同事情的众多原因之一,对吧?

最佳答案

简短回答:是的。您可以很好地恢复给定的提交(即使是旧提交)并且没有冲突。


为什么会这样?

git revert在树的当前顶端创建一个新的提交,它不会删除给定的提交,也不会以任何方式修改它。

merge-base 中的某些内容不同时,您就会发生冲突在您使用还原和 HEAD 创建的提交之间。


亲自尝试一下

简单的例子

给定 repo 树,

Folder1
  file1.txt
  file2.txt
Folder2
  file3.txt

和以下历史,

A---B---C---D << HEAD

在哪里

A 创建所有文件及其内容。
B 修改file2.txt
C 修改file1.txtfile3.txt
D进一步修改file1.txt

然后是命令

git revert B

不会产生任何冲突,只是一个全新的提交 Efile2.txt 进行了新的更改。

A---B---C---D---E << HEAD

git revert 创建的新提交的内容(在评论后添加)

E 中的更改与 B 中引入的更改完全相反。

像这样使用B:

$ git show B
commit f3ba29d98c0998297126d686d03d33794cbc0f73
Author: Pythonista <some.name@some.isp>
Date:   Sun Mar 24 20:41:49 2019 +0100

    Some change

diff --git a/javascript/functions.js b/javascript/functions.js
index 543c9cb..5f166d3 100644
--- a/javascript/functions.js
+++ b/javascript/functions.js
@@ -3710,5 +3710,6 @@ function dumpLists(isMixted) {
 // end of process

 createTrigger(window, 'load', START_EVERYTHING);
+doStuff(param);

你会有一个 E 提交包含:

$ git show E
commit 2ff723970e81d64f3776c081a1f96242589774b6 (HEAD -> master)
Author: Pythonista <some.name@some.isp>
Date:   Sun Mar 24 20:42:33 2019 +0100

    Revert "Some change"

    This reverts commit f3ba29d98c0998297126d686d03d33794cbc0f73.

diff --git a/javascript/functions.js b/javascript/functions.js
index 5f166d3..543c9cb 100644
--- a/javascript/functions.js
+++ b/javascript/functions.js
@@ -3710,6 +3710,5 @@ function dumpLists(isMixted) {
 // end of process

 createTrigger(window, 'load', START_EVERYTHING);
-doStuff(param);

注意最后一个 diff 行前面的 +-,意思是“添加”(+) 和“删除”(-)。


最后,在您的帖子末尾谈谈您的担忧(出于某种原因,我大部分时间都错过了):

我认为您不应该根据对源代码控制的担忧来选择应用程序的架构。 Git 是一个非常棒的工具,它足够聪明,可以避免我们不可避免地遇到的大部分常见问题。寻求根据自己的逻辑对代码进行分组的最佳方法,而不管 git。

顺便说一句,冲突检测发生在 block 级别,而不是文件级别。这意味着同一个文件可能已经被两个源修改而不会引起冲突,如果它们发生在不同的非连续部分。我不能确切地说出阈值在哪里,但这与重点无关。

关于git - 您能否在不造成冲突的情况下恢复除最后一次提交以外的提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55322462/

相关文章:

git - 在 gitbash 中使用 git pull 运行批处理文件

git - 从 Git 中提取的 Grails 代码适用于除一台以外的所有机器

git - 是否可以使用 bazaar、mercurial 或 git 进行部分克隆/分支?

Git Branch 新手 - 如何反转?

git - 我如何撤消 Github 中的先前提交

git - 在 git 中,如何将文件恢复到 3 次提交前?

git - 沉默 git rebase --interactive 的 "how to proceed"消息

git - 如何丢弃 git 子模块中修改的内容?

visual-studio-2015 - Visual Studio 2015 Git 错误消息 "Cannot pull/switch because there are uncommitted changes"

git - 用于恢复多个 git 提交的信息性消息