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>
?
我在C++代码库中有一系列提交。我在一组文件中添加了一个特定的include,我想在整个提交范围内撤销它。有没有什么方法可以自动遍历提交列表,并且对于每一个提交,删除任何匹配的块中的所有行,比如说+#include
,也就是说,如果这一行加上了#include
?
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.
例如,我曾考虑使用git格式-patch和git am,但仅仅删除统一差异中的这些行就会破坏它们。到目前为止,我还没有真正找到任何好的解决方案。
更多回答
git rebase --exec <a command to remove line>
and the command could be something like sed -i '/#include <i_regret_adding_this>/d' file1 file2…
Git rebase--exec<删除行的命令>,该命令可能类似于sed-i‘/#Include/d’file1 File2…
@phd Thank you, but that doesn't exactly do what I want, because it will also remove pre-existing identical lines. And in my particular case that's a problem that's not easy to work around, even if I only limit myself to the files changed in the commit.
@PhD谢谢您,但这并不能完全满足我的要求,因为它还会删除先前存在的相同行。在我的特定情况下,这是一个不容易解决的问题,即使我只将自己限制在提交时更改的文件。
Alas, there is no simple way. With git revert
you can undo all commits completely, but to find out what lines were added you need to parse git diff
.
唉,没有简单的办法。使用git revert,您可以完全撤消所有提交,但要找出添加了哪些行,您需要解析git diff。
About how many files have the problem? Across about how many commits were the mistakes introduced? Is the branch linear during and after the commits you wish to rewrite?
有多少文件有这个问题?大约有多少次失误被引入?在您希望重写的提交期间和之后,分支是否是线性的?
优秀答案推荐
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)
在下面的示例中,我从head~0运行到head~2。(将git ls-files替换为您想要更改的文件列表)
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.
外部循环溢出您想要在其中进行更改的提交。内循环遍历文件。使用git命令,您可以用提交ID标记所有行,然后检查提交ID是否与循环中的提交ID匹配--如果匹配,则删除模式。在此之后,删除所有git指责模式(可能这部分可以改进……可能获得假阳性),并用此输出覆盖文件。
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
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.
分阶段进行调整,这样就不需要调整块标题:执行格式补丁,将添加的包含更改为添加标记的包含,结果是,然后执行筛选分支/筛选回放以删除所有标记的包含。
更多回答
Are you saying that I should essentially search-and-replace in the patch files, replacing the unwanted addition with an addition of some unique string? And then run the patches, and finally end by doing an exec rebase removing the unique string at each commit? That sounds like it would work! Thank you!
您是说我应该在补丁文件中搜索并替换,将不需要的添加替换为添加一些唯一的字符串?然后运行补丁程序,最后通过执行REBASE在每次提交时删除唯一字符串来结束?这听起来好像能行得通!谢谢!
我是一名优秀的程序员,十分优秀!