<p>Each Git hook is executed when a particular Git command is run. See the <a href="https://git-scm.com/docs/githooks" rel="nofollow noreferrer">Git documentation on hooks</a> for specifics. If you have two pushes updating the same ref, whichever one completes the "update" hook first gets to update the ref, and the other will get an error. It doesn't matter which client started to push first. It's all about which got to update the ref first.</p>

<p>When a push occurs, this runs a number of hooks. These three are run before a ref can be updated. </p>

<ul>
<li>pre-push - Client Side, called by git push and can be used to prevent a push from taking place. </li>
<li>pre-receive - Server side, invoked by git-receive-pack on the remote repository. Just before starting to update refs on the remote repository, the pre-receive hook is invoked. Its exit status determines the success or failure of the update. If the hook exits with non-zero status, none of the refs will be updated. If the hook exits with zero, updating of individual refs can still be prevented by the update hook.</li>
<li>update - Server side, invoked by git-receive-pack on the remote repository. Just before updating the ref on the remote repository, the update hook is invoked. Its exit status determines the success or failure of the ref update. The hook executes once for each ref to be updated.</li>
</ul>

<p>My 2 Cents: <strong>I think you're asking the wrong question.</strong> Any use of a Git hook should be quick and simple. If your verification requires more time than a second or two, it's too long and would be misplaced in a Git hook. A long running hook will frustrate users because they'll think Git is unresponsive. My suggestion is to apply the FAIL FAST, FAIL OFTEN principle.</p>

<p>In your case of a long running verification, use of a tool to perform the verification outside of Git is ideal, such as a unit test for example, runnable from CI or locally. Proper use of pull requests (i.e. merging short lived branches) should check that your verification passed and then allow incorporation of such a change.</p>

CC BY-SA 3.0
2017-03-08T23:32:52.113Z
The long-running verification server-side *might* have been acceptable if multiple of them could have been executed in parallel and still all succeed if verification was OK. But that's not happening, so can't use this as shortcut - fallback to candidate-only submissions on client side and automated commits later on, server side. Checking git format-patch workflow next :)
Dan Cornilescu
CC BY-SA 3.0
2017-03-08T23:17:44.953Z
2017-03-08T23:17:44.953Z
Jeremy C
<p>In general git allows concurrent operations because one of them will eventually fail. Some specific database updates will have file locks (like updating the index files) but multiple receives can be in flight at once I think. In this case whichever verification completed first would be allowed in, and the second would fail due to having an invalid history (i.e. not being a fast-forward push).</p>

<p>In general this kind of operation is not well suited to git's server-side hooks since if something does fail, the person will then have to do some surgery on their branches to get things back in a valid state. These kinds of checks are generally run on the workstation side, though then you run into the "fun" that is distributing git hooks as they can't actually be checked in directly.</p>

<p>Another common solution is to have a CI service like Jenkins running verifications (tests) and updating a second branch or a utility tag showing which commits are acceptable.</p>

CC BY-SA 3.0
2017-03-08T18:09:22.160Z
Yeah, this confirms my suspicion - exactly what I was afraid of. And both suggestions (private dev verifications and post-commit CI verifications) have drawbacks which are serious obstacles to large scale integration - which is what I'm trying to address in the 1st place :) More thinking required.
Dan Cornilescu
CC BY-SA 3.0
2017-03-08T06:40:54.643Z
2017-03-08T06:40:54.643Z
coderanger
<p>I'm investigating the possibility of implementing a "pre-commit" verification flow, enforced on the central SCM server side. By "pre-commit" in this paragraph I don't mean the <code>git</code> <code>pre-commit</code> hook, I really mean <em>before</em> the change becomes part of the integration branch, visible to all developers working on the branch.</p>

<p>For <code>git</code> in particular, which is a distributed SCM, the <code>commit</code> phase happens on the local server, which is not what I need. So I can't use the <code>git</code> <code>pre-commit</code> hook. </p>

<p>From what I gather the <a href="https://github.com/git/git/blob/master/Documentation/githooks.txt#L221" rel="nofollow noreferrer"><code>pre-receive</code> hook</a> would be what I'm after:</p>

<blockquote>
  <p>This hook is invoked by 'git-receive-pack' on the remote repository,
  which happens when a 'git push' is done on a local repository. Just
  before starting to update refs on the remote repository, the
  pre-receive hook is invoked.  Its exit status determines the success
  or failure of the update.</p>
  
  <p>This hook executes once for the receive operation. [snip]</p>
  
  <p>If the hook exits with non-zero status, none of the refs will be
  updated. If the hook exits with zero, updating of individual refs can
  still be prevented by the <code>&lt;&lt;update,'update'&gt;&gt;</code> hook.</p>
</blockquote>

<p>Or maybe the related <a href="https://github.com/git/git/blob/master/Documentation/githooks.txt#L259" rel="nofollow noreferrer"><code>update</code> hook</a>:</p>

<blockquote>
  <p>This hook is invoked by 'git-receive-pack' on the remote repository,
  which happens when a 'git push' is done on a local repository. Just
  before updating the ref on the remote repository, the update hook is
  invoked.  Its exit status determines the success or failure of the ref
  update.</p>
  
  <p>The hook executes once for each ref to be updated, [snip]</p>
</blockquote>

<p>The complication is that the verification itself can take a while.</p>

<p>My question: is the execution of these hooks serialized (by <code>git</code>)? Meaning will another hook invocation (due to a subsequent <code>push</code> operation performed <strong>before</strong> the previous hook execution completes):</p>

<ul>
<li>fail,</li>
<li>block until the previous, still running execution finishes,</li>
</ul>

<p>or </p>

<ul>
<li>simply run in parallel with the previous hook execution?</li>
</ul>

<git><git-hooks><workflow>
Are git pre-receive/update hooks serialized?
Dan Cornilescu
# Are git pre-receive/update hooks serialized?

(Asked by: username_0 on 2017-03-08)

I'm investigating the possibility of implementing a "pre-commit" verification flow, enforced on the central SCM server side. By "pre-commit" in this paragraph I don't mean the `git` `pre-commit` hook, I really mean *before* the change becomes part of the integration branch, visible to all developers working on the branch.

For `git` in particular, which is a distributed SCM, the `commit` phase happens on the local server, which is not what I need. So I can't use the `git` `pre-commit` hook.

From what I gather the [`pre-receive` hook](https://github.com/git/git/blob/master/Documentation/githooks.txt#L221) would be what I'm after:

> This hook is invoked by 'git-receive-pack' on the remote repository,
> which happens when a 'git push' is done on a local repository. Just
> before starting to update refs on the remote repository, the
> pre-receive hook is invoked. Its exit status determines the success
> or failure of the update.
>
> This hook executes once for the receive operation. [snip]
>
> If the hook exits with non-zero status, none of the refs will be
> updated. If the hook exits with zero, updating of individual refs can
> still be prevented by the `<>` hook.

Or maybe the related [`update` hook](https://github.com/git/git/blob/master/Documentation/githooks.txt#L259):

> This hook is invoked by 'git-receive-pack' on the remote repository,
> which happens when a 'git push' is done on a local repository. Just
> before updating the ref on the remote repository, the update hook is
> invoked. Its exit status determines the success or failure of the ref
> update.
>
> The hook executes once for each ref to be updated, [snip]

The complication is that the verification itself can take a while.

My question: is the execution of these hooks serialized (by `git`)? Meaning will another hook invocation (due to a subsequent `push` operation performed **before** the previous hook execution completes):

* fail,
* block until the previous, still running execution finishes,

or

* simply run in parallel with the previous hook execution?

**Tags:** git, git-hooks, workflow


---

## 2 answers

### Answer by username_2 on 2017-03-08. Score: 3 | Accepted answer

In general git allows concurrent operations because one of them will eventually fail. Some specific database updates will have file locks (like updating the index files) but multiple receives can be in flight at once I think. In this case whichever verification completed first would be allowed in, and the second would fail due to having an invalid history (i.e. not being a fast-forward push).

In general this kind of operation is not well suited to git's server-side hooks since if something does fail, the person will then have to do some surgery on their branches to get things back in a valid state. These kinds of checks are generally run on the workstation side, though then you run into the "fun" that is distributing git hooks as they can't actually be checked in directly.

Another common solution is to have a CI service like Jenkins running verifications (tests) and updating a second branch or a utility tag showing which commits are acceptable.

> **Comments:**
> **username_0**: Yeah, this confirms my suspicion - exactly what I was afraid of. And both suggestions (private dev verifications and post-commit CI verifications) have drawbacks which are serious obstacles to large scale integration - which is what I'm trying to address in the 1st place :) More thinking required.  

---

### Answer by username_1 on 2017-03-08. Score: 3

Each Git hook is executed when a particular Git command is run. See the [Git documentation on hooks](https://git-scm.com/docs/githooks) for specifics. If you have two pushes updating the same ref, whichever one completes the "update" hook first gets to update the ref, and the other will get an error. It doesn't matter which client started to push first. It's all about which got to update the ref first.

When a push occurs, this runs a number of hooks. These three are run before a ref can be updated.

* pre-push - Client Side, called by git push and can be used to prevent a push from taking place.
* pre-receive - Server side, invoked by git-receive-pack on the remote repository. Just before starting to update refs on the remote repository, the pre-receive hook is invoked. Its exit status determines the success or failure of the update. If the hook exits with non-zero status, none of the refs will be updated. If the hook exits with zero, updating of individual refs can still be prevented by the update hook.
* update - Server side, invoked by git-receive-pack on the remote repository. Just before updating the ref on the remote repository, the update hook is invoked. Its exit status determines the success or failure of the ref update. The hook executes once for each ref to be updated.

My 2 Cents: **I think you're asking the wrong question.** Any use of a Git hook should be quick and simple. If your verification requires more time than a second or two, it's too long and would be misplaced in a Git hook. A long running hook will frustrate users because they'll think Git is unresponsive. My suggestion is to apply the FAIL FAST, FAIL OFTEN principle.

In your case of a long running verification, use of a tool to perform the verification outside of Git is ideal, such as a unit test for example, runnable from CI or locally. Proper use of pull requests (i.e. merging short lived branches) should check that your verification passed and then allow incorporation of such a change.

> **Comments:**
> **username_0**: The long-running verification server-side *might* have been acceptable if multiple of them could have been executed in parallel and still all succeed if verification was OK. But that's not happening, so can't use this as shortcut - fallback to candidate-only submissions on client side and automated commits later on, server side. Checking git format-patch workflow next :)  

---

