Reputation: 10745
I have a feature branch that's grown quite large. There are quite a few lingering TODO comments in our code, but I'd like to find all TODOs added to the code (and not removed yet) on commits not yet merged into master. How might I go about that?
Upvotes: 20
Views: 3218
Reputation: 524
To expand upon @bimlas's answer, use the following script to achieve much better performance:
[alias]
s = "!sh -c ' \
[ $GIT_PREFIX ] && cd $GIT_PREFIX; \
git status --short --branch $*; \
git --no-pager diff -U0 master | \
grep \"^+.*TODO\" | \
sed \"s/^+//\" | \
git --no-pager grep -nFf - -- $(git --no-pager diff --name-only main) 2> /dev/null' -"
Explanation:
The original command first collected all of the lines with TODOs from the diff and then searched the whole repository for them. This is extremely inefficient.
In an ideal world, the final search would not be necessary as we could just tell git diff
to prepend line numbers and file paths to the diff output. However, because this is not possible, we have to find them using git grep
.
We already know that the lines we're looking for can only appear in changed files. Hence, to avoid searching the whole repository, we can limit the git grep
to the changed files. We can achieve that by passing the list of changed files using -- $(git --no-pager diff --name-only main)
.
Upvotes: 0
Reputation: 41
Combine above two answers, I write this code to show TODOs in the HEAD commit.
git --no-pager diff -U0 HEAD^..HEAD | grep -o 'TODO.*$' | xargs -I{} git --no-pager grep -wn -P '{}$' 2>/dev/null
Upvotes: 1
Reputation: 2607
You can use this as an Git alias:
git --no-pager diff -U0 master | \
grep '^+.*TODO' | \
sed 's/^+//' | \
git --no-pager grep -nFf - 2> /dev/null
It shows the added/modified TODO lines of the current branch (compared to master
), but you have to git add
before using it (because of git grep
).
It can be even more usefull if you add it to the status
alias, thus you would be sure that no TODOs remaining when you see the status.
[alias]
s = "!sh -c ' \
[ $GIT_PREFIX ] && cd $GIT_PREFIX; \
git status --short --branch $*; \
git --no-pager diff -U0 master | \
grep \"^+.*TODO\" | \
sed \"s/^+//\" | \
git --no-pager grep -nFf - 2> /dev/null' -"
Example output:
$ git s
## my-branch...origin/my-branch [ahead 2]
M README.adoc
README.adoc:12: // TODO: Add screencast
README.adoc:26: // TODO: Advertise Asciidoctor
Upvotes: 12
Reputation: 1215
You can simply diff your branch against master and grep for TODOs in the output
git diff master..branch | grep "^+.*TODO"
This works great for me assuming enough context in the TODO line.
Upvotes: 17
Reputation: 265717
git grep
can perform a text search on a given tree. git branch --no-merged $commit
gives you all branches not merged into the named commit. Combine the two and you're good to go (I know, you should not use git branch
in scripts, but I couldn't quickly find a way to tell git for-each-ref
to only consider not-merged refs. If anyone has a solution, feel free to comment/edit)
git branch --no-merged master | cut -c3- | while read branch; do
git grep 'TODO' "$branch"
done
Upvotes: 2