从 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”时添加文件失败。在命令提示符下

git status:啥是 UU,为啥要 add/rm 修复它?

我可以修改 git-add 的块大小吗?

在 Git 中提交部分数据

如何在 git add 交互式补丁模式中获得更好的帅哥?

在 git bash 中更改“暂存这个大块”查询的颜色