Ben Dilts
Ben Dilts

Reputation: 10745

Script to find all TODO comments created on a git branch?

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

Answers (5)

Luka Govedič
Luka Govedič

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

zyf0330
zyf0330

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

bimlas
bimlas

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

Neil
Neil

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

knittl
knittl

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

Related Questions