Hacker News new | past | comments | ask | show | jobs | submit login
Githooks: auto-install client-side hooks inside the repos (viktoradam.net)
42 points by rycus86 on July 27, 2018 | hide | past | favorite | 36 comments



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.


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.


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


Huh? Of course I do.


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).


> 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.


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


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."


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.


As much as I agree, this is already an issue with filter in .gitattributes[1].

[1]: https://www.git-scm.com/docs/gitattributes


Filter commands are defined in .git/config, not in .gitattributes.


They can be defined in either. For example, see https://www.agwa.name/projects/git-crypt/.


No. That would be a grave security hole.

In the git-crypt's case, "git-crypt init" adds this to your .git/config:

  [filter "git-crypt"]
          smudge = \"git-crypt\" smudge
          clean = \"git-crypt\" clean
          required = true


Oh, interesting. Completely managed to miss that, thanks!


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.


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

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).


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.


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


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.


Okay that makes sense, thanks for clearing that up for me. That shows my ignorance with Go!


For JS projects, I recommend husky: https://github.com/typicode/husky


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


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.


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`?


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.


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"


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.


That sounds very interesting. Do you have some example code that you can share?


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


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.


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.


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!


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.


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


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.


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: