1

I'd like to have a simple shell command to find my TODOs that are in the diff between my current branch and the repository's main branch.

On our team, we have an agreement, that we do not add new todos to the codebase, but we still have a couple of older todo items in our repository. However, when I work, I like to leave a todo in the code so that I don't forget to look into things or clean up things.

What I could already implement is showing the TODO items in the diff using grep. For example, if the main branch is called develop (but honestly, it would work the same with main, master:

# command
git diff develop HEAD | grep TODO

# output
+      // TODO: How to handle when summary is missing?
+      // TODO: How to handle this error? Exception?
+          // TODO: add function to build basket, maybe?
+        // TODO: Find a better place to set up this mock

This is a good start, but it would be much better if the names of the files (that include these todos) were also printed. Another problem with my current approach is that if there is no message after the TODOs, I can't really search for that in my project (in case the code base has TODOs that were added before (and are part of the main branch)

Vince Varga
  • 6,101
  • 6
  • 43
  • 60
  • 2
    Run a grep (with line #s and file names) for TODO in the committed (HEAD copy) of each file, using `git grep`. Run another grep (with line #s and file names) for TODO in the working copy of each file, using `git grep`. Compare the two results and look for insertions (new TODOs) and deletions (old TODOs that are now gone). – torek Aug 18 '21 at 12:29
  • 1
    https://stackoverflow.com/q/25039242/2834978 – LMC Aug 18 '21 at 13:40
  • 1
    @LMC Thank you for the link, but that is a different question... – Vince Varga Aug 18 '21 at 13:45
  • Try [this diff reformatter I wrote](https://stackoverflow.com/a/65204346/1290731). – jthill Aug 18 '21 at 13:46
  • 2
    A starting point using git diff could be : `git diff -U0 -G TODO`. This should narrow your diff to sections that contain the word `TODO` – LeGEC Aug 18 '21 at 14:09
  • @LeGEC Not sections, but whole files. But still better than nothing. – Socowi Aug 18 '21 at 14:14

1 Answers1

2

Torek's suggestion would look somewhat like this:

# print TODOs from HEAD that are not in develop
comm -23 \
  <(git grep -nFw TODO develop | sed 's/[^:]*://' | sort) \
  <(git grep -nFw TODO HEAD | sed 's/[^:]*://' | sort)

This has a few problems. Since grep -n prefixes each line by its line number, an existing TODO from develop that was moved around by deleting/inserting lines would be listed too. Also, filenames with linebreaks are not handled correctly, but this probably does not matter.

I think the best option would be to parse the output of git diff:

# print TODOs from HEAD that are not in develop
git diff develop HEAD | awk '
  /^diff / {f="?"; next}
  f=="?" {if (/^\+\+\+ /) f=$0"\n"; next}
  /^@@/ {n=$3; sub(/,.*/,"",n); n=0+$3; next}
  /^\+.*TODO/ {print f n ":" substr($0,2); f=""}
  substr($0,1,1)~/[ +]/ {n++}'

The filtered output looks like this:

+++ b/someFile
5:    // TODO: implement this
+++ "b/another file with spaces and a new\nline"
123:TODO in block comment
126:// multiple TODOs in same file

The b/ comes from git diff where b stands for the 2nd tree (here HEAD). All linenumbers are from HEAD.

Using git diff -U0 -G TODO could drastically speed this up if you have a lot of changes but nearly no TODOs

Socowi
  • 25,550
  • 3
  • 32
  • 54
  • Yes, you'd have to strip the line numbers when doing the "what's new" changes, then you'd want to put them back when showing the what-is-new part. That awk script is probably better, especially if there are not that many TODO lines. – torek Aug 19 '21 at 00:17