您能否在不造成冲突的情况下还原除上一次提交以外的其他提交?

Pyt*_*ous 3 git git-revert

注意:stackoverflow的bot认为该问题是主观的,但是非常事实-我在这里不要求意见!

假设我只有一个分支,而我的提交历史如下:A-B-C-D

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

两个问题:

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

  2. 如果是,这是否意味着您只能还原最近的提交?您能否在不造成冲突的情况下还原除上一次提交以外的其他提交?

更新:在@RomainValeri非常有用的澄清后,编辑问题。我认为我在恢复和重置之间造成了太多混乱。在下面的示例中,

git revert B
Run Code Online (Sandbox Code Playgroud)

使分支从

A-B-C-D
Run Code Online (Sandbox Code Playgroud)

A-B-C-D-E
Run Code Online (Sandbox Code Playgroud)

如果B是唯一更改了file2.txt的提交,并且B没有对其他文件进行任何其他更改,则还原后创建的新提交E将保留C和D中所做的所有更改,而不保留B中所做的所有更改。 。 它是否正确?

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

另外:假设我的工作目录中只有一个文件。如果B是唯一更改文件中fun1()函数的提交,而所有其他提交都更改了同一文件中的其他函数,则还原B很可能会引起冲突,因为git会根据文件中的行来考虑,而不是文件中的功能。它是否正确?

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

相反,如果这3个函数中的每一个都在单独的文件中,那么撤消一个提交的更改而不影响其他提交会更简单。

我想当然是单个文件不应太大或包含太多执行不同功能的函数的众多原因之一,对吗?

Rom*_*eri 6

简短的回答:是的。您可以很好地还原给定的提交(甚至是旧的提交)并且没有冲突。


为什么会这样呢?

git revert创建一个新的提交上树的当前尖端的顶部,它并没有删除指定的提交,也不修改任何关系。

当您使用revert和创建的提交之间的合并基础中的某些内容有所不同时,您会发生冲突HEAD


自己尝试一下

琐碎的例子

给定回购树,

Folder1
  file1.txt
  file2.txt
Folder2
  file3.txt
Run Code Online (Sandbox Code Playgroud)

以及历史

A---B---C---D << HEAD
Run Code Online (Sandbox Code Playgroud)

哪里

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

然后命令

git revert B
Run Code Online (Sandbox Code Playgroud)

不会产生任何冲突,只是一个全新的提交E与新的变化file2.txt

A---B---C---D---E << HEAD
Run Code Online (Sandbox Code Playgroud)

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

中的更改EB引入的完全相反的更改。

有了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);
Run Code Online (Sandbox Code Playgroud)

您将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);
Run Code Online (Sandbox Code Playgroud)

注意最后一个差异线前面的+-,意思是“加法”(+)和“删除”(-)。


最后,在您的帖子结尾说一句关于关注的话题(由于某种原因,我最想念的是):

我不认为您应该基于对源代码控制的担忧而为应用程序选择体系结构。Git是一个很好的工具,它足够聪明,可以防止我们不可避免地会遇到的大部分麻烦。寻求最佳方式将代码按照自己的逻辑分组,而不管git如何。

顺便说一句,冲突检测发生在块级别,而不是文件级别。意味着如果同一文件出现在不同的非连续部分中,则可以由两个源修改同一文件而不会引起冲突。我不能确切地说门槛在哪里,但这与重点无关。