admin管理员组文章数量:1334909
There's a file that contains lots of project configuration, including a line that reads something like:
bundleVersion: 1.2.3
I want to find what was the last git commit in my current git log
history, excluding commits that only touch that particular line.
I want something like git log -1 --format='%H' --invert-grep --grep='^\s*bundleVersion:\s[a-zA-Z0-9.]+$'
, except this command only grep for stuff in the git message, and I want it to grep the contents of the commit, not the message.
There's a file that contains lots of project configuration, including a line that reads something like:
bundleVersion: 1.2.3
I want to find what was the last git commit in my current git log
history, excluding commits that only touch that particular line.
I want something like git log -1 --format='%H' --invert-grep --grep='^\s*bundleVersion:\s[a-zA-Z0-9.]+$'
, except this command only grep for stuff in the git message, and I want it to grep the contents of the commit, not the message.
2 Answers
Reset to default 0I guess you can pull it off with a script using a recursive technique.
One iteration that uses commit X
looks like this:
1 find the position of the line you pointed to there on the file on commit X
(tip: git show X:the-config-file
, and make sure to use the colon, otherwise what you are asking for is very different)
2 blame (-w) the config file for commit X
, just that line, so that the blame process is faster. That will give you the commit where that line was introduced in the config file. That commit is from now onC
.
3 C
== X
? If C
is NOT X
, then X
is the commit you are looking for.
4 If X
changed more than just that line in the config, then X
is the commit you are looking for.
5 we need to iterate so run the same process recursively using C~
(keep the pigtail) as X
.
The whole process starts using HEAD
as X
.
The fact that you are doing this makes me think that lots of the changes that are committed are just adjustments to this line? If that is the case and the process is slow using git because it's hundreds or thousands of commits, perhaps?), consider writing something that uses libgit2 (writing something in python is not that complex and it improves speed like crazy because of not starting a git process for each git operation).
You can use git diff-tree -r --name-only $commit~ $commit
to efficiently check whether the commit changes only the file you're interested in, git diff-tree -r --numstat $commit~ $commit
to check whether that changes only one line, and git log --no-walk -pretty=format:ignore -G 'pattern'
to test whether that one line change matches your pattern. If the file's at the top level you can leave off the -r
flag. So you want something like this (very lightly smoketested) script:
path=your.noisy.config
pattern=bundleversion:
git rev-list @ | while read commit; do
# if it doesn't change only the one annoyingly noisy path, we're there
if test x"$(git diff-tree -r --name-only $commit~ $commit)" != x"$path"
then break
fi
# if it doesn't only change a single line in it, we're there
set -- $(git diff-tree -r --numstat $commit~ $commit)
test $1$2 != 11 && break
# if that change doesn't match the annoying pattern, we're there
res=$(git log --no-walk --pretty=format:ignore -G "$pattern" $commit)
test x$res != xignore && break
done
echo $commit | git log --no-walk --stdin
本文标签:
版权声明:本文标题:How to find the last git commit, excluding commits that only touched a particular line of a particular file? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742325629a2453664.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
git log
history (I tweaked the question to reflect that). Like I said, I want something that is like the--invert-grep --grep
I can use ongit log
except that it greps the contents not the messages. – Zorzella Commented Nov 22, 2024 at 19:00