Why not just call a shell script directly? How would you use these with a CI/CD platform?
From an org standpoint you can have them (mandate?) as part of the developer experience.
(Our team doesn't use them, but I can see the potential value)
The prek documentation has a list of many large projects (such as CPython and FastAPI, to name a few) who use it; each link is a PR of how they integrated it into CI if you want to see more: https://prek.j178.dev/#who-is-using-prek
I have a shell utility similar to make that CI/CD calls for each step (like for step build, run make build) that abstracts stuff. I'd have Prek call this tool, I guess, but then I don't get what benefit there is here.
You run the same hooks in CI as locally so it's DRY and pushes people to use the hooks locally to get the early feedback instead of failing in CI.
Hooks without CI are less useful since they will be constantly broken.
Slow hooks are also not a problem in projects I manage as I don't use them.
> Slow hooks are also not a problem in projects I manage as I don't use them.
You bypass the slow hooks you mentioned? Why even have hooks then?
i regularly edit history of PRs for a variety of reasons and avoid pre-commit when possible.
put it all in CI thank you please — gimme a big red X on my pipeline publicly telling me i’ve forgotten to do something considered important.
The checks in those pre-commit hooks would need to be very fast - otherwise they'd be too slow to run on every commit.
Then why would it save time and money if they only get run at the pipeline stage? That would only save substantial time if the pipepline is architected in a suboptimal way: Those checks should get run immediately on push, and first in the pipeline so the make the pipeline fail fast if they don't pass. Instant Slack notification on fail.
But the fastest feedback is obviously in the editor, where such checks like linting / auto-formatting belong, IMHO. There I can see what gets changed, and react to it.
Pre-commit hooks sit in such a weird place between where I author my code (editor) and the last line of defense (CI).
That's still multiple minutes compared to an error thrown on push - i.e. long enough for the dev in question to create a PR, start another task, and then leave the PR open with CI failures for days afterwards.
> But the fastest feedback is obviously in the editor, where such checks like linting / auto-formatting belong, IMHO.
There are substantial chunk of fast checks that can't be configured in <arbitrary editor> or that require a disproportionate time investment. (e.g. you could write and maintain a Visual Studio extension vs just adding a line to grep for pre-commit)
So reviewers have to digest all of the twists and turns I took to get to the final result? Why oh why oh why?
Sure, if they've already seen some of it, then there should be an easy way for them to see the updates. (Either via separate commits or if you're fortunate enough to have a good review system, integrated interdiffs so you can choose what view to use.)
In a better world, it would be the code author's responsibility to construct a meaningful series of commits. Unless you do everything perfectly right the first time, that means updating commits or using fixup commits. This doesn't just benefit reviewers, it's also enormously valuable when something goes wrong and you can bisect it down to one small change rather than half a dozen not-even-compiling ones.
But then, you said "atomic", which suggests you're already trying to make clean commits. How do you do that without modifying past commits once you discover another piece that belongs with an earlier step?
> You just squash on merge.
I'd rather not. Or more specifically, optimal review granularity != optimal final granularity. Some things should be reviewed separately then squashed together (eg a refactoring + the change on top). Some things should stay separate (eg making a change to one scary area and then making it to another). And optimal authoring granularity can often be yet another thing.
But I'll admit, git + github tooling kind of forces a subpar workflow.
Are you asking what advantage pre-commit has over a shell script?
Mostly just functionality: running multiple hooks, running them in parallel, deciding which hooks to run based on the commit files, "decoding" the commit to a list of files, offering a bunch canned hooks, offering the ability to write and install non-shell hooks in a standard way.
The benefit to many of having them as a hook is that you discover it's broken before you pushed your changes, and not when you finally get around to checking the CI on your branch and realising it failed after 30s.
There is of course no reason why you have to have it installed as a precommit hook - many people prefer to run it manually, and the pre-commit tool/prek allows for that.
> you can't force folks to run them
I think it's useful to be able to disable things like this when debugging or reconfiguring them. I sometimes disable the ones I've set up for myself, then reenable them later.
> Why not just call a shell script directly?
Because it's manual; I have to remember to do it each time. But there's no reason not to have a script you can invoke in other ways, if that's something you want.
> How would you use these with a CI/CD platform?
The thing that sets up your environment also installs the git hooks configuration, and/or you can have it invoke specific hooks via CLI.
- very fast? run it all the time (shell prompt drawing, if you want, like direnv)
- fast? run it in a pre-commit hook
- a bit slow? run it in a pre-push book
- really slow? run it in CI, during code review, etc.
Fwiw: I also rewrite history often-ish but it's never that fast for me because I have commit signing turned on and that requires verifying my presence to a USB smartcard on each commit. For me, it's okay if a commit takes a second or two. As it creeps up beyond 3 or 4 seconds, I become increasingly annoyed. If a commit took a minute I would consider that broken, and if I were expected to tolerate that or it were forced on me, I'd be furious.I generally expect an individual pre-commit hook to under ~200ms (hopefully less), which seems reasonable to me. Some of the ones we have are kinda slow (more than 1s) and maybe should be moved to pre-push.
Since you seem especially sensitive to that latency, here's what I'd propose if we worked together:
If you own a repo, let's make all the hooks pre-push instead of pre-commit. On my repos, I like many hooks to run pre-commit. But since the hooks we use are managed by a system that honors local overrides via devenv.local.nix, let's make sure that's in .gitignore everywhere. When I'm iterating in your codebases and I want more automated feedback, I'll move more hooks to pre-commit, and when you're working in mine you can move all my hooks to pre-push (or just disable them while tidying up a branch).