git/Documentation
Karthik Nayak 3bbb0864a2 hook: introduce the receive-report hook
When running 'git-receive-pack(1)', there is no way for the server to
intercept and modify the status report before it is sent back to the
client. Servers with custom logic may need to transform or gate the
report based on the outcome of external logic post reference updates.

This is specially needed for our usecase at GitLab where we have custom
MVCC logic on top of Git which creates a new version for each push
operation. The new version is only committed when certain external
operations post reference transaction succeed. So reporting the correct
message based on the outcome of these operations is important.

The outcome of these operations is only known after `execute_commands()`
has returned and before the report is written. There is no point in
receive-pack where the server can act on that.

We cannot use any of the existing hooks as:

  - The pre-receive hook runs too early, as we haven't updated
    references at that point yet and we need to have the full view of
    all resulting updates (both objects and references).

  - The update hook is too inefficient as it runs once per reference,
    and we cannot trivially determine the last update.

  - The reference-transaction hook is not suited for this. It fires from
    within `ref_transaction_commit()`, which is before the outcome we
    need to report is known, so there is no phase at which it could give
    us the answer. It also does not contain any knowledge regarding the
    push and cannot communicate with the clients.

  - The proc-receive hook replaces execute_commands() for references
    matching 'receive.procReceiveRefs'. We need to gate the report for
    the push as a whole.

  - The post-receive and post-update hooks cannot be used as they run
    too late, at the point where we have already reported success to the
    client.

Introduce a new 'receive-report' hook. The hook receives the complete
pkt-line encoded status report on standard input, after all ref updates
have been applied to the repository by execute_commands() but before the
report is sent to the client. See linkgit:gitprotocol-pack[5] details on
the protocol structure.

The hook's stdout fully replaces the report sent to the client.
receive-pack fully buffers the hook's stdout before acting on the exit
status, so the exit code is known before the client receives anything.
This gives two distinct behaviors depending on exit status:

- Exit 0: the hook's stdout is used as the report. The hook can
  rewrite 'ok' lines to 'ng' lines to signal per-ref rejection to the
  client while receive-pack itself exits cleanly. The client marks
  rejected refs as '[remote rejected]' and exits with a non-zero
  status if any ref is 'ng'.

- Non-zero exit: the hook's stdout is discarded, receive-pack modifies
  all references to be rejected with a 'receive-report hook failed'
  error.

In both cases, any output the hook writes to standard error is
forwarded to the client over the sideband channel and appears as
'remote:' lines on the client terminal. Writing to stderr alone does
not affect the push outcome.

Reference updates applied by execute_commands() are not rolled back in
either failure mode. The hook can cause the client to perceive the push
as failed, but cannot undo server-side changes. This creates a
divergence that the server cannot resolve: the client leaves its
remote-tracking reference at the old value while the update is in fact
applied, and a later fetch may reveal the update that the push reported
as rejected.

The hook is therefore only appropriate for servers which can guarantee
that a rejected update is not observable by any reader. In our case the
transaction committed by execute_commands() produces a candidate version
which is not visible to other readers and is only published once the
subsequent operations succeed, so a report of 'ng' corresponds to a
version that is discarded rather than published. On a repository where a
committed reference update is immediately visible, rejecting a push from
this hook would instead leave the pusher with a view that does not match
the server.

This hook does not use the config-based hook infrastructure, which
supports running multiple scripts per hook event. This hook is a
bidirectional filter: it receives the report on stdin and writes a
modified version to stdout. Running multiple such scripts sequentially
would require piping the output of one into the input of the next,
which the current hook infrastructure does not support. A single-script
design is therefore a natural fit, and is consistent with how
'proc-receive' is structured for the same reason.

Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-11 14:28:40 -07:00
..
RelNotes The 22nd batch 2026-09-02 09:21:59 -07:00
config odb/files: be less aggressive with geometric repacking 2026-08-21 10:19:14 -07:00
howto
includes
mergetools
technical Merge branch 'jc/rerere-doc-typofix' 2026-09-02 09:21:59 -07:00
.gitignore
BreakingChanges.adoc safe.bareRepository: default to "explicit" with WITH_BREAKING_CHANGES 2026-04-27 14:50:54 +09:00
CodingGuidelines Merge branch 'jc/doc-timestamps-in-stat' 2026-05-11 10:05:54 +09:00
DecisionMaking.adoc
Makefile Documentation/technical: add paint-down-to-common doc 2026-08-11 07:34:31 -07:00
MyFirstContribution.adoc Merge branch 'wy/doc-myfirstcontribution-trim-quotes' 2026-07-19 10:42:18 -07:00
MyFirstObjectWalk.adoc
ReviewingGuidelines.adoc
SubmittingPatches Merge branch 'ss/submittingpatches-typofix' 2026-08-25 10:53:32 -07:00
ToolsForGit.adoc
asciidoc.conf.in doc: convert git-bisect to synopsis style 2026-05-25 20:05:44 +09:00
asciidoctor-extensions.rb.in
blame-options.adoc
build-docdep.perl
cat-texi.perl
cmd-list.sh
config.adoc Merge branch 'kh/doc-replay-config' 2026-08-11 10:07:00 -07:00
date-formats.adoc doc: document and test `@` prefix for raw timestamps 2026-06-02 18:13:12 +09:00
diff-algorithm-option.adoc
diff-context-options.adoc diff: document -U without <n> as using default context 2026-03-10 06:17:59 -07:00
diff-format.adoc diff-format.adoc: mode and hash are 0* for unmerged paths from index only 2026-05-16 22:21:37 +09:00
diff-generate-patch.adoc
diff-options.adoc doc: convert git-format-patch synopsis and options to new style 2026-07-23 14:26:58 -07:00
doc-diff
docbook-xsl.css
docbook.xsl
docinfo-html.in
everyday.adoco
fetch-options.adoc Merge branch 'wy/docs-typofixes' 2026-06-16 09:01:03 -07:00
fix-texi.sh
for-each-ref-options.adoc doc: fix some style issues in git-clone and for-each-ref-options 2026-02-05 21:14:05 -08:00
format-patch-caveats.adoc doc: convert git-am synopsis and options to new style 2026-05-25 20:05:44 +09:00
format-patch-end-of-commit-message.adoc doc: convert git-am synopsis and options to new style 2026-05-25 20:05:44 +09:00
fsck-msgids.adoc
generate-mergetool-list.sh
git-add.adoc add: introduce '--resolved' option 2026-07-31 08:52:16 -07:00
git-am.adoc doc: convert git-am synopsis and options to new style 2026-05-25 20:05:44 +09:00
git-annotate.adoc
git-apply.adoc doc: convert git-apply synopsis and options to new style 2026-05-25 20:05:44 +09:00
git-archimport.adoc
git-archive.adoc archive: document --prefix handling of absolute and parent paths 2026-04-08 11:13:52 -07:00
git-backfill.adoc pack-objects: support sparse:oid filter with path-walk 2026-05-24 18:41:06 +09:00
git-bisect-lk2009.adoc
git-bisect.adoc bisect: add --reset-when-found to leave when done 2026-08-02 16:34:36 -07:00
git-blame.adoc blame: reserve mark column only if necessary 2026-07-06 07:34:48 -07:00
git-branch.adoc branch: add --dry-run for --delete-merged 2026-08-05 10:08:28 -07:00
git-bugreport.adoc
git-bundle.adoc
git-cat-file.adoc cat-file: unify default format 2026-08-07 18:50:08 -07:00
git-check-attr.adoc
git-check-ignore.adoc
git-check-mailmap.adoc
git-check-ref-format.adoc
git-checkout-index.adoc
git-checkout.adoc checkout -m: autostash when switching branches 2026-04-29 21:46:03 +09:00
git-cherry-pick.adoc
git-cherry.adoc
git-citool.adoc
git-clean.adoc
git-clone.adoc Merge branch 'cc/lop-filter-auto' 2026-02-25 11:54:17 -08:00
git-column.adoc
git-commit-graph.adoc doc: add caveat about turning off commit-graph 2026-05-08 10:22:33 +09:00
git-commit-tree.adoc
git-commit.adoc
git-config.adoc doc: git-config: escape erroneous highlight markup 2026-06-11 12:08:17 -07:00
git-count-objects.adoc
git-credential-cache--daemon.adoc
git-credential-cache.adoc
git-credential-store.adoc
git-credential.adoc
git-cvsexportcommit.adoc
git-cvsimport.adoc
git-cvsserver.adoc
git-daemon.adoc
git-describe.adoc doc: convert git-describe manual page to synopsis style 2026-04-06 09:38:19 -07:00
git-diagnose.adoc
git-diff-files.adoc
git-diff-index.adoc
git-diff-pairs.adoc
git-diff-tree.adoc
git-diff.adoc
git-difftool.adoc doc: convert git-difftool manual page to synopsis style 2026-04-06 09:38:18 -07:00
git-fast-export.adoc fast-export: standardize usage string and SYNOPSIS 2026-07-13 08:54:29 -07:00
git-fast-import.adoc fast-import: use parse_options() for command line options 2026-08-11 07:33:17 -07:00
git-fetch-pack.adoc
git-fetch.adoc
git-filter-branch.adoc
git-fmt-merge-msg.adoc
git-for-each-ref.adoc
git-for-each-repo.adoc
git-format-patch.adoc doc: convert git-format-patch synopsis and options to new style 2026-07-23 14:26:58 -07:00
git-format-rev.adoc doc: format-rev: use [synopsis] on code block 2026-08-17 13:33:06 -07:00
git-fsck-objects.adoc
git-fsck.adoc
git-fsmonitor--daemon.adoc fsmonitor: implement filesystem change listener for Linux 2026-04-15 08:44:33 -07:00
git-gc.adoc
git-get-tar-commit-id.adoc
git-grep.adoc doc: convert git-grep synopsis and options to new style 2026-05-25 20:05:44 +09:00
git-gui.adoc
git-hash-object.adoc
git-help.adoc
git-history.adoc builtin/history: implement "drop" subcommand 2026-07-03 10:32:47 -07:00
git-hook.adoc doc: hook: don’t self-link via config include 2026-05-22 09:36:20 +09:00
git-http-backend.adoc
git-http-fetch.adoc http: avoid concurrent appends to partial packs 2026-07-27 12:57:20 -07:00
git-http-push.adoc
git-imap-send.adoc doc: convert git-imap-send synopsis and options to new style 2026-07-23 14:26:58 -07:00
git-index-pack.adoc
git-init-db.adoc
git-init.adoc
git-instaweb.adoc
git-interpret-trailers.adoc trailers: stop recognizing URLs as trailers 2026-08-21 08:53:27 -07:00
git-last-modified.adoc
git-log.adoc doc: log: use the same delimiter in description list 2026-04-28 09:46:26 +09:00
git-ls-files.adoc ignore: note info/exclude lives in GIT_COMMON_DIR, not GIT_DIR 2026-05-13 10:25:52 +09:00
git-ls-remote.adoc
git-ls-tree.adoc
git-mailinfo.adoc
git-mailsplit.adoc
git-maintenance.adoc
git-merge-base.adoc
git-merge-file.adoc merge-file: honor merge.conflictStyle outside of a repository 2026-02-07 17:04:26 -08:00
git-merge-index.adoc
git-merge-one-file.adoc
git-merge-tree.adoc
git-merge.adoc
git-mergetool--lib.adoc
git-mergetool.adoc
git-mktag.adoc
git-mktree.adoc
git-multi-pack-index.adoc midx: support custom `--base` for incremental MIDX writes 2026-05-20 11:31:13 +09:00
git-mv.adoc
git-name-rev.adoc
git-notes.adoc
git-p4.adoc
git-pack-objects.adoc pack-objects: support `--delta-islands` with `--path-walk` 2026-06-21 16:26:14 -07:00
git-pack-redundant.adoc
git-pack-refs.adoc
git-patch-id.adoc doc: patch-id: see also git-cherry(1) 2026-02-17 10:49:51 -08:00
git-prune-packed.adoc
git-prune.adoc
git-pull.adoc
git-push.adoc push: support pushing to a remote group 2026-05-04 10:11:17 +09:00
git-quiltimport.adoc
git-range-diff.adoc Merge branch 'sp/doc-range-diff-takes-notes' 2026-05-31 10:00:39 +09:00
git-read-tree.adoc
git-rebase.adoc rebase: support --trailer 2026-03-06 13:02:20 -08:00
git-receive-pack.adoc hook: introduce the receive-report hook 2026-09-11 14:28:40 -07:00
git-reflog.adoc
git-refs.adoc doc: refs: linkgit to git-maintenance(1) 2026-08-06 10:32:49 -07:00
git-remote-ext.adoc
git-remote-fd.adoc
git-remote-helpers.adoco
git-remote.adoc
git-repack.adoc builtin/repack: add guards for --drop-filtered 2026-08-13 13:34:50 -07:00
git-replace.adoc doc: add caveat about turning off commit-graph 2026-05-08 10:22:33 +09:00
git-replay.adoc doc: replay: move “default” to the right-hand side 2026-07-30 09:15:04 -07:00
git-repo.adoc repo: add path.gitdir with absolute and relative suffix formatting 2026-06-23 21:15:52 -07:00
git-request-pull.adoc doc: convert git-request-pull synopsis and options to new style 2026-07-23 14:26:58 -07:00
git-rerere.adoc doc: fix singular/plural mismatch in git-rerere 2026-04-16 21:22:01 -07:00
git-reset.adoc
git-restore.adoc Merge branch 'kh/doc-restore-double-underscores-fix' 2026-05-19 09:57:45 +09:00
git-rev-list.adoc
git-rev-parse.adoc
git-revert.adoc
git-rm.adoc
git-send-email.adoc doc: convert git-send-email synopsis and options to new style 2026-07-23 14:26:58 -07:00
git-send-pack.adoc
git-sh-i18n--envsubst.adoc
git-sh-i18n.adoc
git-sh-setup.adoc
git-shell.adoc
git-shortlog.adoc doc: convert git-shortlog manual page to synopsis style 2026-04-06 09:38:19 -07:00
git-show-branch.adoc
git-show-index.adoc
git-show-ref.adoc
git-show.adoc doc: convert git-show to synopsis style 2026-02-05 21:14:05 -08:00
git-sparse-checkout.adoc doc: fix typos via codespell 2026-06-08 00:21:35 +09:00
git-stage.adoc
git-stash.adoc stash: add --label-ours, --label-theirs, --label-base for apply 2026-04-29 21:46:02 +09:00
git-status.adoc
git-stripspace.adoc
git-submodule.adoc doc: convert git-submodule to synopsis style 2026-02-05 21:14:05 -08:00
git-svn.adoc ignore: note info/exclude lives in GIT_COMMON_DIR, not GIT_DIR 2026-05-13 10:25:52 +09:00
git-switch.adoc checkout -m: autostash when switching branches 2026-04-29 21:46:03 +09:00
git-symbolic-ref.adoc
git-tag.adoc
git-tools.adoc
git-unpack-file.adoc
git-unpack-objects.adoc
git-update-index.adoc
git-update-ref.adoc
git-update-server-info.adoc
git-upload-archive.adoc
git-upload-pack.adoc
git-url-parse.adoc doc: describe the url-parse builtin 2026-05-06 09:48:29 +09:00
git-var.adoc doc: replace git config --list/-l with `list` 2026-04-06 09:57:07 -07:00
git-verify-commit.adoc
git-verify-pack.adoc
git-verify-tag.adoc
git-version.adoc
git-web--browse.adoc
git-whatchanged.adoc
git-worktree.adoc Merge branch 'sb/doc-worktree-prune-expire-improvement' 2026-02-09 12:09:10 -08:00
git-write-tree.adoc
git.adoc Merge branch 'os/doc-git-custom-commands' 2026-03-16 10:48:14 -07:00
gitattributes.adoc userdiff: add support for Swift 2026-07-23 07:14:34 -07:00
gitcli.adoc
gitcore-tutorial.adoc
gitcredentials.adoc
gitcvs-migration.adoc doc: gitcvs-migration: rephrase “man page” 2026-04-06 09:57:07 -07:00
gitdatamodel.adoc
gitdiffcore.adoc
giteveryday.adoc
gitfaq.adoc
gitformat-bundle.adoc
gitformat-chunk.adoc
gitformat-commit-graph.adoc
gitformat-index.adoc ignore: note info/exclude lives in GIT_COMMON_DIR, not GIT_DIR 2026-05-13 10:25:52 +09:00
gitformat-loose.adoc rust: add a new binary object map format 2026-02-07 17:41:03 -08:00
gitformat-pack.adoc midx: do not require packs to be sorted in lexicographic order 2026-02-24 11:16:33 -08:00
gitformat-signature.adoc
gitglossary.adoc
githooks.adoc hook: introduce the receive-report hook 2026-09-11 14:28:40 -07:00
gitignore.adoc ignore: note info/exclude lives in GIT_COMMON_DIR, not GIT_DIR 2026-05-13 10:25:52 +09:00
gitk.adoc
gitmailmap.adoc
gitmodules.adoc doc: fix grammar errors in submodule description 2026-04-16 21:22:01 -07:00
gitnamespaces.adoc
gitpacking.adoc Documentation: fix broken `sampleRate` in gitpacking(7) 2026-05-12 10:36:18 +09:00
gitprotocol-capabilities.adoc
gitprotocol-common.adoc
gitprotocol-http.adoc
gitprotocol-pack.adoc doc: gitprotocol-pack: normalize italic formatting 2026-03-02 21:35:05 -08:00
gitprotocol-v2.adoc cat-file: unify default format 2026-08-07 18:50:08 -07:00
gitremote-helpers.adoc
gitrepository-layout.adoc
gitrevisions.adoc
gitsubmodules.adoc
gittutorial-2.adoc
gittutorial.adoc doc: replace git config --list/-l with `list` 2026-04-06 09:57:07 -07:00
gitweb.adoc
gitweb.conf.adoc
gitworkflows.adoc
glossary-content.adoc gitglossary: fix indentation of sub-lists 2026-04-13 11:50:06 -07:00
i18n.adoc
install-doc-quick.sh
install-webdoc.sh
line-range-format.adoc
line-range-options.adoc line-log: allow non-patch diff formats with -L 2026-05-29 14:06:21 +09:00
lint-delimited-sections.perl
lint-documentation-style.perl
lint-fsck-msgids.perl
lint-gitlink.perl
lint-man-end-blurb.perl
lint-man-section-order.perl
lint-manpages.sh
manpage-bold-literal.xsl
manpage-normal.xsl
manpage.xsl
merge-options.adoc
merge-strategies.adoc
meson.build Merge branch 'mm/git-url-parse' 2026-05-21 12:06:48 +09:00
object-format-disclaimer.adoc
pack-refs-options.adoc
pretty-formats.adoc docs/pretty-formats: add %(count) and %(total) 2026-03-23 13:06:58 -07:00
pretty-options.adoc
pull-fetch-param.adoc
ref-reachability-filters.adoc
ref-storage-format.adoc docs: correct information about reftable 2026-04-08 07:18:56 -07:00
rerere-options.adoc doc: rerere-options.adoc: link to git-rerere(1) 2026-02-10 12:27:07 -08:00
rev-list-description.adoc
rev-list-options.adoc graph: add --[no-]graph-indent and log.graphIndent 2026-07-14 07:32:51 -07:00
revisions.adoc remote: find tracking branches for URL push destinations 2026-07-22 11:29:49 -07:00
scalar.adoc
sequencer.adoc
signoff-option.adoc
texi.xsl
trace2-target-values.adoc
transfer-data-leaks.adoc
urls-remotes.adoc
urls.adoc
user-manual.adoc doc: replace git config --list/-l with `list` 2026-04-06 09:57:07 -07:00