从 git add -p 编辑大块时修复“补丁不适用”
Posted
技术标签:
【中文标题】从 git add -p 编辑大块时修复“补丁不适用”【英文标题】:Fixing "patch does not apply" when editing a hunk from git add -p 【发布时间】:2014-05-10 13:06:24 【问题描述】:我对代码文件进行了一系列更改,并在暂存之前执行git add -p path/to/file.hpp
检查差异。
总结一下我的更改:我已将常规类声明转换为模板类定义。在这样做的过程中,我从文件底部取出一大块代码并将其移到顶部(现在需要在类之前定义一个异常类),然后我替换了一堆-liners(方法声明),每个都有几行代码(方法实现)。
Git 无法正确检测到我的更改的上下文,并且基本上已经在一个大杂烩中删除和添加了行,其中两条相邻的行之间根本没有任何联系差异。为了使更改更易于稍后检查,我转移了一堆更改以使它们在上下文中,但小心地保持所有添加和删除的行以相同的顺序,保持添加和删除的行数不变等等.
完成后,我收到错误消息
error: patch failed: include/aof/physics/magnetic-field.hpp:143
error: include/aof/physics/magnetic-field.hpp: patch does not apply
Your edited hunk does not apply. Edit again (saying "no" discards!) [y/n]?
好的,所以我在某个地方犯了一个错误。好的,我会再试一次。再次发送相同的消息。
如果我在上面回答y
,我可以回到我编辑的补丁,但是因为我不知道它有什么问题,所以对我没有多大帮助。在尝试多次编辑补丁失败后,我不禁想知道:有没有办法在这里获得更好的错误消息?我如何找出为什么补丁不适用,所以我可以修复它?
简化示例以阐明我要完成的工作
原始补丁。不太容易看到这里发生了什么......
- ClassConstructor(const OtherClass& other, double d);
+ ClassConstructor(const TOtherClass& other, double d) : _other(other), _d(d)
- void method1() const;
- double calculation() const;
- double otherCalculation() const;
+ _a = 1 / d;
+
- ~ClassDestructor() ; // Yes, of course it's more sensibly named
- ;
+ void method1() const
+ // this method does nifty stuff.
- struct my_exception_type : public std::runtime_error
- my_execption_type() : runtime_error("oops!")
- virtual const char* what() const throw()
- std::ostringstream cnvt;
- cnvt << runtime_error::what() ": Sorry, I shouldn't have done this...";
+ double calculation() const
+ return _a + _d;
+
- return cnvt.str().c_str();
+ double otherCalculation() const
+ return 0.; // I'm lazy
+ ~ClassDestructor() ; // Yes, of course it's more sensibly named
;
我尝试将其编辑为的内容。 (此编辑在 SO 完成,因此不确定这个特定的是否有问题,但您知道我正在对大块进行什么样的编辑)。更容易理解这些变化,你不觉得吗?
- ClassConstructor(const OtherClass& other, double d);
+ ClassConstructor(const TOtherClass& other, double d) : _other(other), _d(d)
+ _a = 1 / d;
+
- void method1() const;
+ void method1() const
+ // this method does nifty stuff.
+
- double calculation() const;
+ double calculation() const
+ return _a + _d;
+
- double otherCalculation() const;
+ double otherCalculation() const
+ return 0.; // I'm lazy
+
;
- struct my_exception_type : public std::runtime_error
- my_execption_type() : runtime_error("oops!")
-
- virtual const char* what() const throw()
- std::ostringstream cnvt;
- cnvt << runtime_error::what() ": Sorry, I shouldn't have done this...";
- return cnvt.str().c_str();
- ;
显然,在正确的空行数等方面存在很大的出错风险,但我的问题不仅在于很难确保它全部正确 - 也很难弄清楚我犯了什么错误.
【问题讨论】:
这个问题有帮助吗:***.com/questions/3268596/… ? @LeGEC:这个问题在故障排除方面提供了有用的指导,但它并没有真正让我比我目前拥有的更多。这些信息对我来说都不是全新的,也不是我当前的补丁所特有的(无论当前的补丁是什么)。这个问题是,如果有办法从git
本身中挤出更多信息的错误消息。
我不确定我是否完全理解您想要实现的目标。您是否正在尝试编辑补丁,以便 git 记住“第 1 行”实际上是“第 13 行”的替代品,“第 2 行”实际上是“第 26 行”的替代品,等等...?
@LeGEC:我做了一个简化的例子,它与实际案例非常接近。我希望它能澄清事情。
【参考方案1】:
您不能使用git add -p
告诉 git “保留此补丁作为此文件两个版本之间差异的跟踪”:git 确实 不 存储差异或补丁,它存储实际 内容。
当您在 git (git add myfile
) 中添加文件时,该文件的特定版本将收到基于其唯一 内容 的哈希值。 Git 将不跟踪它是如何从版本 n-1 到版本 n。
当你运行git diff
时,git实际上会检索文件的两个版本的内容,并再次运行diff算法。您尝试编辑的补丁不会保存在内存中。
我能想到的最接近的方法是为 diff 算法本身添加“同步点”:
1- 从文件的第一个版本开始,在每个“迁移块”上提交带有 cmets 的第一个中间版本:
// migrating method1 :
void medthod1() const;
//migrating calculation :
void calculation() const;
//etc ...
2- 在第一次提交之后,写下你的实际迁移,保留 cmets:
// migrating method1 :
void method1() const
//this method does nifty stuff
// migrating calculation :
void calculation() const
return _a + _d;
//etc ...
并提交此版本。
3- 最后,删除不需要的、嘈杂的 cmets,并提交最后一个版本。
在浏览 git 历史时,迁移将显示为 3 次提交,在检查提交 2-
引起的差异时,您应该清楚地了解重写的内容。
【讨论】:
好的。因此,无论如何,我试图完成的基本上是毫无意义的。好吧,感谢您对原因进行了很好的解释! 你也可以改变 git 的 diff 算法,例如--patience
,在这种情况下通常会提供更好的结果。以上是关于从 git add -p 编辑大块时修复“补丁不适用”的主要内容,如果未能解决你的问题,请参考以下文章
如何修复:错误:'<filename>' 没有提交检查致命:输入“git add”时添加文件失败。在命令提示符下