Question

I've made a bunch of changes to a code file, and do git add -p path/to/file.hpp to inspect the diff before I stage it.

To summarize my changes: I've converted a regular class declaration to a template class definition. In doing so, I've taken a large chunk of code from the bottom of the file and moved it to the top (an exception class that now needed to be defined before the class), and then I've replaced a bunch of one-liners (method declarations) with a few lines of code each (method implementations).

Git wasn't able to detect the context of my changes correctly, and basically had deleted and added lines in a big mish-mash, where there wasn't necessarily any connection at all between two lines next to each other in the diff. In order to make the changes easier to inspect later, I shifted around a bunch of changes to get them in context, but was careful to keep all added and removed lines in the same order, keep number of lines added and deleted unchanged and so on.

When I was done, I got the error message

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]? 

OK, so I made a mistake somewhere. Fine, I'll try again. Same message again.

If I answer y above, I can get back to my edited patch, but since I don't know what's wrong with it that doesn't help me very much. After trying to edit the patch unsuccesfully a handful of times, I can't help but wonder: is there a way to get a better error message here? How do I figure out why the patch doesn't apply, so I can fix it?

Simplified example in order to clarify what I'm trying to accomplish

Original patch. Not very easy to see what's going on here...

-        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
     };

What I attempt to edit it to. (This edit done here at SO, so not sure if this particular one is problematic or not, but you get the idea of what kind of edits I'm doing to the hunk). Much easier to understand these changes, don't you think?

-        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();
-    };

Obviously, there's a big risk of making mistakes with having the number of blank lines correct etc, but my problem isn't only that it's difficult to make sure that it's all correct - it's also difficult to figure out what mistakes I made.

Was it helpful?

Solution

You cannot use git add -p to tell git "keep this patch as a trace for the differences between the two version of this file" : git does not store diffs or patches, it stores actual content.

When you add a file in git (git add myfile), this specific version of the file will receive a hash based on its sole content. Git will keep no trace of how it went from version n-1 to version n.

When you run git diff, git will actually retrieve the content of the two versions of the file, and run the diff algorithm again. The patch you are trying to edit will not be kept in memory.


The closest way I can think of to achieve what you are looking for is to add "sync points" for the diff algorithm itself :

1- Starting from the first version of your file, commit a first intermediary version with comments over each "migration block" :

// migrating method1 :
void medthod1() const;

//migrating calculation :
void calculation() const;

//etc ...

2- After this first commit, write your actual migration, keeping the comments :

// migrating method1 :
void method1() const {
    //this method does nifty stuff
}

// migrating calculation :
void calculation() const {
    return _a + _d;
}

//etc ...

and commit this version.

3- Finally, remove the unneeded, noisy comments, and commit this last version.

When exploring the git history, the migration will show up as 3 commits, you should have a clear view of what was rewritten when inspecting the differences intoduces by commit 2-.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top