
Githooks: auto-install client-side hooks inside the repos - rycus86
https://blog.viktoradam.net/2018/07/26/githooks-auto-install-hooks/
======
inetknght
I absolutely do not ever want git to automatically install things when I clone
or sync. Copying only.

This is _begging_ for nefarious things to be installed automatically.

~~~
mehrdadn
I'm less worried about nefarious things and more worried about incompetence. A
careless rm -rf ${PWD}/build (or cp or whatever) can nuke/overwrite/etc. my
files if it happens inside a folder with a space in it. Because of issues like
this I really don't trust anyone to writing scripts that execute automatically
on a random machine. Heck, I only barely trust me to do it for myself.

~~~
meddlepal
So you never download and run programs you haven't written or audited?

~~~
mehrdadn
Huh? Of course I do.

~~~
derefr
I think the parent is saying that there's just as high a chance of
incompetence in the installer of a random third-party app, or the install
script of an unvetted third-party package, as there is of a theoretical "post-
clone script" of an arbitrary Git repo.

The difference, I would say, is that installers and packages are created by
ops people, and Git hooks are written by developers or devops people. Decide
for yourself which one is more likely to make a mistake that reformats your
system. (It's actually a hard question: developers are usually more precise
with syntax in languages [like Bash] where ambiguous syntax can be dangerous;
while ops people are better at understanding the system-level implications of
the actions they're asking the system to perform.)

(Also, unlike installers or packages, there's no reason for a Git repo's hooks
to be privileged to do anything outside of the Git repo's cloned .git dir +
worktree. If Git wanted synced scriptability, it would be a perfect case for
application-level sandboxing, using system calls like OpenBSD's pledge(2).

~~~
mehrdadn
> there's just as high a chance of incompetence in the installer of a random
> third-party app

This is what you're missing though. No proper programming language performs
automatic word splitting on spaces. Only shell scripting languages like like
Bash do. There's a reason I didn't conflate "script" with "app" like you guys
have. Scripts are both missing critical features for robust coding and also
make it really easy to play fast and loose with everything. "Decide for
yourself which one is more likely to make a mistake that reformats your
system" is exactly what I have done in making the distinction here.

~~~
derefr
You can write Git hooks in any language, not just Bash. They can be compiled
Haskell binaries, even.

~~~
mehrdadn
It's as if I had written "I think automotive regulation is necessary; I'd be
worried about car companies producing cars without safety features", and in
response you're replying with "companies can make cars with a variety of
safety features. They can include seat belts and airbags, even."

~~~
derefr
Like I was saying, it would make sense for Git to sandbox its hooks. One valid
way of doing this is to replace arbitrary-executable hooks with hooks that run
in a sandboxed scripting environment, such as an embedded Lua interpreter; or
hooks that are compiled to target a sandboxed VM, such as ZeroVM, PNaCl, or (a
different profile of) WASM.

I wasn’t suggesting that we actually allow devs to sync bash scripts around,
although I _was_ pointing out that that’s what we’re presently already doing
with e.g. Debian package hook scripts.

------
bluehatbrit
I've not used Go before, but I'm not convinced Go over bash is a benefit in
this scenario. It's introducing another dependency and more complexity into
the solution, making it less useful for people who don't work with Go. Perhaps
it's not aimed at those of us, that's fine but making something less portable
to make it easier to build seems like a frustrating trade-off from a user
perspective.

Obviously this is an open source side project, so it won't cater to everyone,
I'm just skeptical of it being the benefit that it's claimed to be.

~~~
prophesi
You only need to install Go if you're wanting to manually build the project
(which is a good idea for security reasons). You otherwise just add the
compiled binary to your path and you're good to go.

He gives his reasonings for it here: [https://github.com/git-hooks/git-
hooks/wiki/Why-golang](https://github.com/git-hooks/git-hooks/wiki/Why-golang)

The tl;dr is that it will eventually have features that would be nontrivial to
implement with bash, and Go is easier on the development-side than C (coming
from a frontend dev experience).

~~~
yjftsjthsd-h
You would also need the tool chain if you're not on the same platform as built
it originally, unless I just skimmed over it outputting multiple binaries and
selecting them by local system type. Otherwise I clone a project on my Mac and
it tries to run the binaries at the last developer built on her Raspberry Pi.

~~~
prophesi
No, it's pretty easy to set up cross-compilation with Go 1.5+. You'd just
download the correct package for your OS.

Luckily for you, the project already has binaries built for Mac (Darwin):
[https://github.com/git-hooks/git-hooks/releases](https://github.com/git-
hooks/git-hooks/releases)

~~~
yjftsjthsd-h
Oh, I misunderstood; I thought you were shipping binaries in the git rep to be
run as hooks, not that git-hooks itself was written in Go. If it's the git-
hooks itself then yeah portability should be good. I do notice that you're
only releasing binaries for Darwin and Linux; no love for the BSDs? Not that
it's a big deal, since most Go stuff is trivial to build on any supported
platform.

------
andrethegiant
For JS projects, I recommend husky:
[https://github.com/typicode/husky](https://github.com/typicode/husky)

~~~
iBelieve
Agreed, Husky is great. I like using it with lint-staged
([https://github.com/okonet/lint-staged](https://github.com/okonet/lint-
staged)) to run ESLint and Prettier
([https://github.com/prettier/prettier](https://github.com/prettier/prettier)).

------
yjftsjthsd-h
I see no discussion of security implications. Of course, _frequently_ if
you're cloning a repo you're about to execute out of it anyways, but not
always.

------
paulddraper
I've yet to see a convincing reason for githooks.

Is it not a violation of abstraction to turn your version control system into
a build/test/CI system?

Local staging, committing, rebasing, cherry-picking, etc. operate on arbitrary
line-delimited text. I should be able to do those without triggering non-VCS
things.

Do you want to add a convenient auto format step with your IDE, githooks, or
inotifywait? Okay. But changing how a standard, fundamental tool works for
everyone...

What's wrong with `make format`?

~~~
qznc
I'm not sure about this at all.

Most checks should be in the CI but git hooks allow a team to add rules
without affecting all teams at once. When rules turn out good they can be
enforced on everybody via CI. Even a single team might have dozens of
machines, so they don't want to roll out git hooks manually.

This is the niche use case I can think of. Still, it exploits git to do things
it is not made for. This is asking for trouble elsewhere.

------
georgewfraser
Git hooks are great for formatters, but it's a big problem for large teams
that you can't auto-install them on everyones machine. Of course I realize why
git refuses to do this. At my company (Fivetran) we ended up writing a Java
annotation processor that simply checks if you've installed the git hooks, and
if you haven't it throws a big error message that says "YOU NEED TO RUN
install_git_hooks.sh"

~~~
Dunedan
The solution I prefer is to run all hooks as part of CI as well. So whenever
somebody doesn't have them installed locally his builds will just fail if he
did something the hooks would've caught.

The next he time he'll think twice if he should wait for the failed CI build
or just install the hooks locally.

------
nmca
When I've done this before, I just had an "install-hooks" script. What's the
need for auto-install?

------
goerz
Something I've done on some projects is to install (or check) the hooks as a
side-effect of a script that any contributor is guaranteed to run. In my case,
`./configure`. The Makefile would be another place for this (`make test`). It
just copies the hooks from `.hooks` to `.git/hooks` and chmods them to be
executable. This solves the problem of contributors (or myself) forgetting to
set up the proper hooks in every checkout, and it's very low-maintenance.

~~~
bluehatbrit
Please consider not doing this if you're doing some sort of public / open
source work. You're effectively installing software on someone's computer
which they may not be directly aware of and that triggers silently in the
background. I'm sure you're not nefarious, but if your project were
compromised you could easily see issues of downloaded code from the compromise
repo being run without the users knowledge.

Internally / privately it's generally a lesser risk, but if this is open
source please consider removing that feature for better security. That or
document it incredibly clearly.

~~~
goerz
I don’t see your point. By definition, the build scripts that are part of the
repo always execute arbitrary code (e.g. any line in the makefile).
Interacting with any compromised repo is always a security risk. Granted, my
approach is a bit hacky, but it’s not even modifying anything outside of the
checked out folder!

~~~
bluehatbrit
My point is, by auto-installing hooks it's making a predictable command,
unpredictable. As a user I would not be able to happily run git commands in a
repo after a git clone until I've reviewed any hooks that may have been
installed. If a user does not review those scripts then it's a security flaw,
if a user always review them then it's getting in the way more by forcing
someone to do that on every clone.

Build scripts are explicitly called by a user, a git hook is a side effect
they've elected to setup. In this case the tool is adding side effects to
commands without the user explicitly choosing to have them.

I can see someone downloading a repository, running a few git commands to make
a couple of changes and not realising the git hooks have been installed and
the behaviour of a command has changed. Once you're near that scenario, you're
just opening up security holes rather than fixing them. It'd be better to have
a script one can run after a git clone explicitly that is documented in the
project repository.

"To setup git hooks to speed up development, run ./init-hooks." is easy,
clear, makes it difficult to do it without knowing what's happening.

~~~
goerz
I guess a good alternative is to have the build tools refuse to do anything
until the user/developer has installed the proper hooks by running ./init-
hooks (as opposed to executing ./init-hooks silently in the background). I
agree that's a preferable way to do it in a public project: explicit is better
than implicit

~~~
bluehatbrit
I agree, that sounds like a much better approach. In a private or companies
internal project it's probably not an issue, you already "trust" the code
you're downloading.

I tend to have some sort of setup or bootstrap script which the docs promote
as the way to prepare for development. This tends to install any dev
dependencies and also sets up hooks (which is always optional). This works
fairly well in most cases, combine that with a lint on the CI and most people
don't have any problems. It also saves assuming someone wants git hooks just
because they're pulling code, often they just want to build and run it.

------
rhoml
I love this projects because they aim to enforce best practices. I particular
like pre-commit.com. Fairly easy to set up and a large variety of plugins
already.

