git

Git revert all lines that match a pattern


enter image description here

I mistakenly replace all and save lines in my documents that are all tracked by Git. I have done some work before and forgot to commit as a checkpoint before doing that, so reverting is not desirable as it would revert all of my work. I would like to revert only the replace all operation using help from Git.

I know all the lines that I need to revert because they all have the same new line. From GUI tools like SourceTree I can click Discard Hunk one by one, but there are many such location that I would like to discard. All the places I would like to revert has new line that says

m_Sprite: {fileID: 21300164, guid: 791de2a5646d94a15a09bb1d7e79a0e6, type: 3}

But old line is not necessary the same. (In fact there are 2 kinds of old lines that I changed into this same new ones) Are there any scripted way to match the pattern of changed lines so I can selectively revert them all? Thank you.

Using git add -p interactively to add everything except the hunk I don't want going forward is very tedious, since it ask you one by one but there are so many works to add and at the same time the hunks I don't want are mixed in almost every file. (So I must be very careful on every question git asks) The same goes for git checkout -p to remove the hunks I don't want going backward.


Solution

  • Ok, I managed to fix the problem using a patch.

    First, I commit this messed up state as a checkpoint. Then I can produce a patch of this state (the one with replaced lines I want to revert plus all the work I don't want to lose) and the previous commit (the one with correct lines remembered) using

    git diff --binary HEAD^ HEAD > ~/Desktop/patch.diff

    Note that the previous commit comes first in the command.

    With the patch saved somewhere, I reset hard into the previous commit and git clean -f. Now, if I git apply patch.diff I would arrive at the same point (but still keeping head on a previous commit) The idea is to directly edit the patch surgically before applying.

    The patch is composed of hunks, so to disable a certain hunk I don't want the approach is to replace the + lines with the same thing as the preceeding - ones. I can use regex searching in VSCode to search multi-lines with \n (Don't forget to escape the + character as \+ so it does not count as regex) and replace them all.

    This way is better than removing the hunks, since there's no chance to corrupt the format of a patch. The patch does not know if it is changing into the same line, doing nothing.

    enter image description here

    After editing the patch and apply, I got all the changes minus the hunks that we edit earlier. And so it equals the action of "reverting all the hunks I don't want".