0

I am sure it is a repeated question and apologies to bother. I didn't find solution to my usecase yet. I created a pre-commit hook that prevents commit when newly developed code has sonar issues. Since it is a pre-commit hook there might be a chance that developer can disable this hook using --no-verify option and I want to avoid it.

NOTE: I can't use pre-receive hook in this usecase because newly developed code will be on developer's machine and hence the hook should be triggered as client-side hook.

Is there anyway to enforce this hook to be executed before commit (out of developer control) without skipping it? I found a similar stack overflow question where the answers suggests to use pre-receive hook which works on push event not on commit event. Now I just want to run pre-commit hook without developer control. If this is not possible, Is there any alternative? so that I can confirm the hook execution before pushing the code.

I know that --no-verify option is git internal command and we have less chances to control it. I want to know if pre-receive hook can help me in ensuring the execution of pre-commit hook before push event. Thanks in advance

Manu M
  • 57
  • 5
  • Regarding: "I can't use pre-receive hook in this usecase because newly developed code will be on developer's machine". Can you use both a pre-commit and a pre-receive hook? (Or possibly even better depending on your workflow, a gated checkin on completing a merge into a shared branch.) – TTT Feb 19 '23 at 18:57
  • Depending on usecase we can use both hooks. I can use pre-commit on client side to control commit event and use pre-receive hook on server side to control push event but for my usecase If commit event can't be controlled, I need to control push event. If a developer disables pre-commit hook, then my pre-receive hook should stop the code push onto Gitlab server – Manu M Feb 20 '23 at 02:22
  • I'm not sure what your hook does, but in general pre-commit hooks are helpful suggestions, and not something you should mandate. If someone is only partially done with something that wouldn't pass the pre-commit hook, they should still be allowed to commit their work if they want to, perhaps to save their work so they can stop and work on something else. IMHO they should be able to push partially done work as well, as long as it is on a personal branch and a not a shared one. I would only enforce specific rules when pushing or merging into a shared branch. – TTT Feb 20 '23 at 02:49
  • To maintain code quality I developed a pre-commit hook that will prevent newly developed code (with in the developers' machine) from being committed onto git repo if the code has sonar issues. To ensure this happens, I need to make the hook execution mandatory – Manu M Feb 20 '23 at 04:12
  • There is no absolute way to control what can happen on the client side -- you focus on *hooks* but keep in mind a user can create *any content* in his local copy of the repo. The only place where you can *enforce* some rules with some reasonable control is on the central server. Your pre-commit hook is certainly useful, if you find that too many people are skipping it check the reasons why (e.g: does it force the developpers to see their action hanging for several seconds when running `git commit` ?), if you need to *enforce* its rules, double it with a check on the central repo. – LeGEC Feb 20 '23 at 06:13
  • Developers skipping the hook is just an 'if' case. Now I am looking for a pre-receive hook that can check whether pre-commit hook has been executed or not before a commit. This idea seems ok but not sure how to proceed on it. Consider this way, I will run a pre-commit hook and then commit happened when I try to push pre-receive in server should be triggered and checks for pre-commit execution. If hook is executed then push happens else push will be halted. – Manu M Feb 20 '23 at 07:03
  • On the server side you shouldn't care whether the pre-commit hook was ever executed. Just check what you want to check and block it if it fails the check. If the developer finds the pre-commit useful they'll use it. If they purposefully avoid it, they'll get the bad news that they failed the check at push time. – TTT Feb 20 '23 at 07:23
  • @TTT I got your point. In server side I need not care about the execution of pre-commit hook but since I am unable to control client side I just want to control from server side and the conditions that I want to check should be executed before commit hence I can't check them with pre-receive hook. It's a requirement and I am helpless – Manu M Feb 20 '23 at 07:40
  • “Is there anyway to enforce this hook to be executed before commit (out of developer control) without skipping it?”—No. (1) You can’t even enforce what hooks that the “client” uses (security concerns: arbitrary code) and you can’t enforce that they are ever run. (2) There isn’t a “hooks have been run” state in a Git repository, and even if there was would you trust it? (3) All git repositories are equal; a “main repository” can’t enforce what another one does. The *only* thing that it can do is to restrict what it accepts itself… with pre-receive. – Guildenstern Mar 29 '23 at 21:12

1 Answers1

1

No there is no such option. The user always has full control over which hooks are executed on their own machine.

You commit-hook also won't be created for a user after doing a git clone, installing the hooks is also up to the developer.

One thing you could do is to add a bit of code that will ensue the repo configuration in the build and/or test scripts. Then add two things:

  1. The pre-commit hook to ensure the code was tested
  2. A git alias that replaces git commit and throws when the --no-verify flag is passed in.

The only way to know whether this code as ran is to add something to the commit. Can be a something you add to the commit message or you coud add a note to the commit:

git notes add -m "Pre-commit hook added this marker"

That way you can check for that note on the server from a pre-receive hook.

It is still no guarantee the commit was actually tested or built. To add such a guarantee you can only use a pull-request workflow and run the build and tests as part of the checks.

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
  • 1
    Yes. I know that scope is low. I am just checking for an alternative. Commit can happen in 2 ways here, commit without running hook and commit after running hook. I was asked to check even if a developer disable pre-commit hook and try to commit, can we use a pre-receive hook to distinguish between these commits? If commit happens after running pre-commit hook, pre-receive will allow you to push code else halt pushing the code. I think the scope for this is even low because git commit is an internal operation and we have nothing to do with it. I am just trying for luck – Manu M Feb 19 '23 at 18:33
  • You could see if you could at least verify the existence of the git hooks on the client in the build scripts, that would make it hard to 'forget to install them'. You could force install an alias from that same build script that throws an error when people try to commit with `--no-verify` this A should help you in that direction: https://stackoverflow.com/a/69262214/736079. That should do the trick in most cases – jessehouwing Feb 19 '23 at 21:11
  • Yes even adding notes to commit msg doesn't gaurantee the hook execution because developer can disable the hook and can commit with notes that misleads the pre-receive hook. I think there isn't appropriate solution for this – Manu M Feb 20 '23 at 10:31
  • @ManuM “I was asked to check even if a developer disable pre-commit hook and try to commit, can we use a pre-receive hook to distinguish between these commits?”—When someone emails you a phone number, is there a way for you to know that they ran the script `validate-phone.pl` before they decided to mail it to you? No. – Guildenstern Mar 29 '23 at 21:15