How To Format Only Staged Files With Spotless

How To Format Only Staged Files With Spotless

As a developer, you know that keeping your code clean and consistent is crucial for the success of any project. One tool that can help you achieve this is Spotless, a powerful code formatting plugin for Gradle and Maven. However, you may find yourself in situations where you only want to apply Spotless to the files that have been staged in your Git repository. In this post, we'll explore how to do just that.

First, let's define what we mean by "staged files." In Git, a staged file has been modified and added to the Git index, which means it is ready to be committed. This is different from an unstaged file, which has been modified but not yet added to the index.

With definitions out of the way, we then want to create a bash script that will invoke Spotless (this assumes you already have Spotless set up in your project). In this setup, the script will be invoked as a pre-commit Git hook. The script also presumes the presence of a .zshrc file. Some slight modifications would be needed to make this compatible with bash.

This script will do the following:

  1. Stash any unstaged files

  2. Apply Spotless to the remaining files

  3. Add any modified files from Spotless to the git index

  4. Cleanup the stash from step 1

#!/bin/zsh

# Workaround for Git GUI users to have environment variables available (https://community.atlassian.com/t5/Bitbucket-questions/SourceTree-Hook-failing-because-paths-don-t-seem-to-be-set/qaq-p/274792)
source ~/.zshrc

# Immediately exit if any command has a non-zero exit status
set -e

echo "Running formatter..."

# Creaate a patch file
GIT_STASH_FILE="stash.patch"

# Stash unstaged changes
git diff > "$GIT_STASH_FILE"

# add the patch so it is not stashed
git add "$GIT_STASH_FILE"

# stash untracked files
git stash -k

# apply spotless
./gradlew spotlessApply --daemon

# re-add any changes that spotless created
git add -u

# store the last exit code
RESULT=$?

if test -f "$GIT_STASH_FILE";
then
  echo "$GIT_STASH_FILE has been found"

    # apply the patch
    git apply stash.patch --allow-empty

    # delete the patch and re-add that to the index
    rm -f stash.patch
    git add stash.patch
else
    echo "$GIT_STASH_FILE has not been found"
fi

# delete the WIP stash
git stash drop

# return the exit code
exit $RESULT

That's it! Now, whenever you commit changes to your Git repository, Spotless will be applied to only the staged files. This ensures that your code is always clean and consistent, which can save you time and headaches down the line.

In conclusion, applying Spotless to only the staged files in your Git repository via a bash script in a pre-commit hook is a straightforward process that can improve the quality and consistency of the code that you want to commit, while leaving unstaged code alone. By following the steps outlined in this blog post, you can easily integrate Spotless into your development workflow and enjoy the benefits of clean code.