To develop my projects, I take advantage of gitโs hooks.
The ones I use most commonly are pre-commit and pre-push.
My scripts try to do a quick verification during the pre-commit, a longer and more vigorous test for pre-push.
Just recently I ran into an error during compilation during the CI stage. It would break, but my hooks both showed that there was no error. This would greatly troubling to me, because I had to trust that if both tests passed, that it absolutely work in the CI stage.
After a significant amount of debugging through multiple CI cycles, I found the bug, and it revealed to me why this was happening. In my git repo I had 2 files. One was staged and I wanted to commit and push it. The other was one I had in my working index. Not ready to deploy just yet, a WIP (Work in Progress).
What happened is this WIP file would allow the build to work, but when this change was not pushed and thus not available to the CI git pull, caused the build to fail!
This post helped lead me to a working solution.
Itโs a big hackish, but how it works is like this:
- Create a new commit with a comment of โWIPโ
- Stash all existing changes
- Restage to the commit before WIP (undo the WIP)
- Do my verification steps
- Pop the stash and restore the files
stash_set=false
git commit --no-verify --message "WIP"git stash --keep-index -u && stash_set=truegit reset --soft HEAD^
# Verification logic# [...]
if [[ $stash_set == true ]]; then git stash popfiSwitching to Manual
I ran with this for a few days, but I ran into a number of issues. For example, squashing multiple commits caused the pre-commit hook to run and fail, because it couldnโt find the right commit. Initially, I tried to put in some workarounds. However, this did not feel conclusive and prone to unknown errors in the future.
if [[ "${GIT_REFLOG_ACTION}" =~ "rebase".*"reword" ]]; then # [...]fiSo, instead I decided to move it into a command runner. I use just. The stash command verifies there is files that can be stashed, makes a WIP commit, stashes the extra and restores it.
stash: #!/usr/bin/env bash if git diff --cached --quiet; then git commit --no-verify --message "WIP" git stash --keep-index -u -m "WIP_STASH" git reset --soft HEAD^ else git stash --keep-index -u -m "WIP_STASH" firestore: git stash list | grep "WIP_STASH" && git stash pop --index