Rewrite history to remove all additions of lines matching a certain pattern

113 Views Asked by At

I have a range of commits in a C++ codebase. I added a particular include in a set of files that I want to undo for the whole range of commits. Is there any way of automatically going through the list of commits, and for each commit, remove all lines in any of the hunks that match say +#include <i_regret_adding_this>, i.e if the line adds #include <i_regret_adding_this>?

I've considered using for instance git format-patch and git am, but just removing such lines in the unified diffs corrupt them. So far I haven't really found any good solution.

2

There are 2 best solutions below

0
manish ma On

This is a bit hacky... but might work.

In below example I ran from HEAD~0 till HEAD~2. (replace git ls-files with the list of the files you want to change)

Outer loop runs over commits you want to do the change in. Inner loop runs over files. With git blame you mark all lines with their commit IDs, then check if commit ID matches commit ID from loop - if match then delete pattern. After this delete all git blames patterns (probably this part can be improved... could get false positives) and overwrite file with this output.

for i in {0..2}; do for file in $(git ls-files); do git blame $file | sed -e "/$(git rev-parse --short HEAD~$i).*#include <i_regret_adding_this>/d" -e 's#[0-9].*(*.) ##g' > $file; done; done
1
jthill On

Do the adjustment in stages so adjusting hunk headers doesn't get necessary: do the format-patch, change the additions of that include into the addition of a marked include, am the result, then do a filter-branch / filter-repo to remove all the marked includes.