是否可以通过编程方式从母版中删除单个过去的修订版?

时间:2019-01-08 14:07:24

标签: git revision-history

假设我有一个带有多个修订版本的文件;

initial commit text
revision one
revision two
revision three
revision four

稍后,我想删除一些在多个修订版本中发生的更改,但是要保留以后的更改,例如,仅删除第二个修订版本中所做的更改;

initial commit text
revision one
revision three
revision four

当前,我正在调用第二个版本的diff,并手动搜索和替换主版本,但是我想知道是否有某些功能可以让我简单地取出该先前的版本,并且我想应用以后所有的内容吗?

编辑:根据我不清楚的内容,这些方法都无法完全解决。此处的“代码”代表要还原的文件的实际文本,因此,当我建议删除第二个修订时,我的意思是说“第二个修订”的文字文本。

我已经尝试了rebase和revert工具,它们之所以失败,是因为添加了以下两行“修订版3”和“修订版4” ...好吧,我一直在文件最终读取的地方遇到合并冲突;

initial commit text
revision one
<<<<<<< HEAD
revision two
revision three
revision four
=======
>>>>>>> parent of 4ac4327... revision 2

与此同时出现错误的文本(此文本是用于还原的,尽管变基类似于)

error: could not revert 4ac4327... revision 2
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'

只要回退一步,删除文本“修订版四”,我就可以使用还原或重新设置,但是我的任何尝试似乎都失败了。

我尝试进行添加和提交,当我--continue时,我得到

error: no cherry-pick or revert in progress

然后我将文件中的另外三个git消息归档。

编辑二:我认为我正在寻找的过程是在第一个修订版中签出,然后使用git cherry-pick ...一旦我在这里找到所有内容,我将对其进行更新... < / p>

4 个答案:

答案 0 :(得分:5)

git revert添加了一个 new 提交,该提交撤消了给定提交所做的任何操作。例如,给定

a initial commit text
b revision one
c revision two
d revision three
e revision four

(在左边带有一些确实被截断的假设哈希),您可以运行

git revert c

产生类似

的东西
a initial commit text
b revision one
c revision two
d revision three
e revision four
f revision five

f等同于您现在正在做的事情:撤消在c的差异中找到的内容。

与重新部署相比,这带来的风险要小,并且对于已经共享的分支机构来说是安全的。

答案 1 :(得分:1)

您可以使用interactive rebase删除提交。

interactive rebase的步骤,

  1. git rebase -i <revision before the one to delete>
  2. 在文本编辑器中,删除所需的提交
  3. 保存并退出编辑器

注意:一删除后的提交将被重写。如果分支已经被推送,则执行变基将迫使您不得不强制推送分支。除非您确定自己是使用该分支的唯一开发人员,否则这应该是与您的团队共同努力的结果。

答案 2 :(得分:1)

在撰写本文时,以前有两个答案。每个人都提到一种方法来完成您要问的事情。但是缺少一些上下文,如果您要决定使用哪个上下文,那将非常重要。

撤销对git中的一次提交所做的更改的预期方法是更改​​为git revert <commit>的提交。正如chepner解释的那样,这将创建一个新的提交,该提交将从目标提交中撤消“补丁”。 <commit>参数可以是提交ID(目标提交唯一的哈希值),也可以是指向该提交的表达式(例如HEAD~2-意思是“从当前选中的位置返回2, out commit”-在您的示例中。)

请注意,如果提交3或4的更改与从2的更改重叠,则还原会产生冲突,必须像合并冲突一样解决冲突。另外,有时git revert与合并提交之间的交互会引起问题-但这仅在您要还原的内容是合并,或者如果它是已在其中包含更改的提交时才重要以后合并。如果您搜索“还原合并”或类似内容,则应该找到详细说明这些问题的现有答案(应该出现)。

人们有时不愿接受该解决方案的原因是,他们不希望自己的历史显示他们现在认为自己的错误。我会客观地说这不应该是优先事项,但是有一些选择可以从历史记录中删除目标提交……这是有代价的。

这些替代方法统称为历史记录重写。如果历史记录是共享的,则他们可以将存储库置于导致其他用户出现问题的状态,直到执行清理为止;如果他们执行的清理不正确,则它将撤消更改并将提交2放回原处。 。因此,您必须确保所有回购用户都参与其中。

此外,历史记录重写几乎总是冒着创建损坏提交的风险。这是因为您正在以自动方式重写提交3和4,从而创建了未经测试的代码状态。由于4是新的“分支尖端”,因此您可能会对其进行测试;但是如果您也不进行测试3,则可能是历史记录中断,可能会干扰以后的故障排除(例如,使用git bisect)。

可以使用诸如git rebase -igit filter-branch之类的命令来重写历史记录,但是在决定以这种方式使用它们之前,应确保了解上述问题。我建议阅读git rebase文档中的“从上游基础恢复中”一节;一般适用于历史记录重写。

答案 3 :(得分:0)

问题已解决

我面临的问题是工具问题,而我对diff和merge缺乏了解。

我对diff的唯一熟悉是在github / gitlab上阅读提交消息,这非常简单。从命令行来看,这对我来说是一种全新的体验,我发现的大多数教程要么是不会引发错误的简单测试用例(删除上一个修订版),要么是假设用户理解了更复杂情况下所需的更改,例如我正在描述。

当git(恢复原值,还原或选择条件)采取措施并抛出错误时,它(对于许多人来说可能是显而易见的,但对我自己而言不是)将这些错误写入文件本身。我遇到的奇怪消息是修复程序本身,我只是没有上下文知识。我用于diff / merge的工具试图以最简单的方式来修复这些错误并没有帮助,即返回我试图删除的非常提交。我仍然不知道如何使用该工具删除那些零件,并且我已经停止尝试。我为vim放了一个快速宏,现在一切都很好。

因此,问题不在于git,而在于diff。执行适当的git操作,当git抛出错误时,请解决文件本身中的问题,并了解在HEAD和=======之间标记了更改,并在其后跟随尾随提交,这就是sha哈希。继续执行git操作,它不应引发任何其他错误。