Because of a tool that I use, certain comment lines keeps being added to my code.
// Added by blahblah
Since I can't turn off this behavior, I want to configure Git to automatically remove that comment line from both local file and commit.
I want to configure Git to do these:
- Remove
// Added by blahblahcomment lines
There can be multiple Tab or Space in front of the comments I want to remove.
The comments must be removed for both local files and commit. - Re-stage modified files
I'm not sure if this is needed or not, but if it is needed, it should do so.
So, after Git completes its job, the comment lines must be removed from both local file and commit (and remote repository too).
First thing I've tried was using IDEA's File Watchers plugin.
If I register a script that removes that comment line, the problem would be solved because the comment line is removed before Git creates commit and the commit won't have that comment line.
So 'No comment in local file, No comment in commit too'.
I wrote a bash script for it.
#!/bin/bash
# this script is located at '.script' directory
scriptdir="$(dirname -- "$0")"
cd "$scriptdir/../src" || exit
java_files=$(find . -type f -name "*.java")
for java_file in $java_files; do
sed -i '/^[[:space:]]*\/\/ Added by blahblah/d' "$java_file"
done
But File Watchers kept running when I enable my watcher task.
I expected the task to be run only once for every file save, but it kept running infinitely.
Because File Watchers task is executed every seconds, it conflicted with currently opened editor's content. This prevented me to edit code at all.
So I gave up using File Watchers plugin.
Next thing I've tried was using Git Hooks.
In my theory, if I set Git Hooks correctly, Git would edit my local files before making any commit. Since my local files are edited before commit, both local files and files in the commit won't have such comment lines.
I wrote prepare-commit-msg like this.
#!/bin/bash
# this script is located at '.git/hooks' directory
print "$PWD"
scriptdir="$(dirname -- "$0")"
cd "$scriptdir/../../src" || exit
echo "$PWD"
java_files=$(find . -type f -name "*.java")
for java_file in $java_files; do
sed -i '/^[[:space:]]*\/\/ Added by blahblah/d' "$java_file"
done
But nothing were changed as if there was no such hook present. pre-commit also didn't work.
Here is updated version of the prepare-commit-msg, but this doesn't work either.
#!/bin/bash
TMP_FILE=$(mktemp)
for FILE in $(git diff --cached --name-only --diff-filter=AM); do
if [[ $FILE == *.java ]]; then
sed -e '/^[[:space:]]*\/\/ Added by blahblah/d' "$FILE" > "$TMP_FILE"
cat "$TMP_FILE" > "$FILE"
git add "$FILE"
# This doesn't work neither
#sed -i -e '/^[[:space:]]*\/\/ Added by blahblah/d' "$FILE"
#git add "$FILE"
fi
done
exit 0
Last thing I've tried was to use .gitattributes's filter.
I added these line into .gitconfig.
[filter "nocomment"]
clean = "sed -i -e '/^[[:space:]]*\\/\\/ Added by blahblah/d' %f"
smudge = ""
required = true
And this line to .gitattributes.
*.java filter=nocomment
Since I only need to 'remove' lines, not 'restore' them, I left smudge as empty.
But this didn't remove the comment line from local file. Git might remove that line for commit, but that's not what I want.
(I'm using Git for Windows, and this might be the reason of something doesn't work properly...?)
Here is working pre-commit script's content.
#!/bin/bash
set -x # This thing is new... Thanks for the information!
for FILE in $(git diff --cached --name-only --diff-filter=ACM); do # '--diff-filter' is needed
if [[ $FILE == *.java ]]; then # I only have to process java file
echo Removing comment from ${FILE}
sed -i '/^[[:space:]]*\/\/ Added by blahblah/d' "$FILE"
git add "$FILE" # This line was already in second attempt
fi
done
The reason that Git hooks didn't run as if they weren't present was I set git config --global core.hooksPath before. This prevented hooks in .git/hooks from running...
Now everything works as intended. Thank you!
I'm not going to comment on the IDEA FileWatcher plugin, because an IDE is not a substitute for proper automation.
These are well-documented, here.
But the linked docs explicitly say
It's just for altering the message, after the staged changes are final. Let's pretend you wrote your script as the correct hook instead,
pre-commit.There are a few mistakes in both of your attempts, but you could have debugged them all quickly by adding
set -xat the top and just running the script. You don't need git to invoke it for you, just test it yourself.If we combine the unbroken parts of both, it is only missing one thing: you changed the working tree, but didn't stage your changes for inclusion in the commit.
Proof: