1

I'm currently working on a large legacy project which undergoes quite some refactoring.
As you can guess this also means lots of deletions etc..

At the moment I'm removing a specific feature which has become obsolet, so I want to keep my changes related to the removal of this feature. While I'm doing this I noticed quite some code which can be removed since it's not used (for example unused class fields etc.).

Now I don't want to remove this stuff yet, since I would have to review every class later on when I want to commit the removal of the feature, to keep my commit focused. So I used a little TODO like comment (// @REMOVE) which marks unnecessary code so I can remove it later on.

And now comes the question: Is it possible to automate interactive adding to ignore added lines which just consist of this TODO comment, in other words which match a specific pattern? I know I can search for patterns while adding interactivly but it would be great if I wouldn't need to do it manually.

Many thanks in advance!


Note I know that Eclipse for example marks unused fields etc. but since these fields always have a setter and are annotated for injection (it's a JSF project), so this won't help me.


ANSWER

Thanks to RomanGotsiy's suggestion I was able to create a bash pre-commit hook which does exactly what I asked for. I marked his answer as correct since he pointed me in the right direction.

#!/bin/sh
#
# This pre-commit hook checks for the specified pattern and removes the matching lines from the index before commiting
# THe lines will still be included in the working tree

pattern="// @REMOVE"

function pre-commit-echo {
    echo "PRE-COMMIT: $@"
}

for file in $(git diff --name-only --cached); do
    # Skip if the file doesn't exist
    [ -e "$file" ] || continue

    index_content=$(git show :$file)
    if echo "$index_content" | grep "$pattern" > /dev/null; then
        pre-commit-echo "Remove lines containing \"$pattern\" from file \"$file\""

        # Save working tree file content
        file_content=$(cat "./$file")

        # Remove the lines for the commit
        { echo "$index_content" | grep -v "$pattern"; } > "$file"
        git add "$file"
        # Reset the file to the old state
        echo "$file_content" > "$file"

        # Ensure commit isn't empty
        if [ -z "$(git diff --name-only --cached)" ]; then
            pre-commit-echo "Commit is empty. Abort." 1>&2
            exit 1
        fi
    fi
done

exit 0
Sascha Wolf
  • 18,810
  • 4
  • 51
  • 73

1 Answers1

1

You could use git-hooks.

I've written simple hook on python that solves you problem.

Hook on gist

#!/usr/bin/env python
import sys
import re
import os
import subprocess

OPEN_TAG = r"// @REMOVE"
END_TAG = r"// @"

def git(args):
  args = ['git'] + args
  git = subprocess.Popen(args, stdout = subprocess.PIPE)
  details = git.stdout.read()
  details = details.strip()
  return details

if __name__ == '__main__':
  staged_files = git(["diff", "--name-only", "--cached"])
  print
  print "PRE-COMMIT HOOK"
  print "removing unnecessary code before commit"
  for file in staged_files.split("\n"):
    file_contents = open(file).read()
    # remove from file unnecessary code wrapped int OPEN_TAG and END_TAG
    cleared_contents, replaces_count = re.subn(r"{}(.*?){}".format(OPEN_TAG, END_TAG), "", file_contents, flags=re.S)
    open(file, 'w').write(cleared_contents)
    # add cleared file to stage and as result to commit
    git(["add", file])

    # restore original file
    open(file, 'w').write(file_contents)

    print("  {}: removed {} chunks".format(file, replaces_count))
  print "# done"
  print


To enable this hook, put following code to ".git/hooks/pre-commit" and allow this file execution ($ chmod +x pre-commit on Linux)

Sascha Wolf
  • 18,810
  • 4
  • 51
  • 73
RomanHotsiy
  • 4,978
  • 1
  • 25
  • 36
  • I believe you misunderstood my question. I don't want to remove the code, I just want to ignore the `// @REMOVE` lines. But nethertheless thanks for the effort. – Sascha Wolf Jul 14 '14 at 13:54
  • You can easily modify this script for you problem! Just change regular expression. If you don't know python or regular expressions I can do it for you. – RomanHotsiy Jul 14 '14 at 14:02
  • You just need to change this part of code: `re.subn(r"{}(.*?){}".format(OPEN_TAG, END_TAG), "", file_contents, flags=re.S)` to this `re.subn(r"// @REMOVE.*$", "", file_contents, flags=re.S)`. – RomanHotsiy Jul 14 '14 at 14:11
  • I've created a bash pre commit hook which does what I need. Nethertheless I'll mark your answer as correct since you pointed me in the right direction. – Sascha Wolf Jul 14 '14 at 14:48