Skip to content

post-commit/post-checkout hooks use nohup, which Git for Windows' shell lacks — rebuild fails silently #1161

Description

@rv-us

Summary

The git hooks installed by graphify hook install background the graph rebuild with nohup ... &. Git for Windows' bundled shell (MSYS/MINGW64) does not ship nohup (nor
setsid), so the line dies with nohup: command not found and the rebuild never runs. Worse, it fails silently: git commit / git pull return success, no error surfaces to
the user, and the knowledge graph just quietly goes stale.

Environment

  • OS: Windows 11
  • Shell running the hooks: C:\Program Files\Git\usr\bin\sh.exe (Git for Windows, MSYSTEM=MINGW64)
  • git version 2.42.0.windows.2
  • graphify installed under conda Python; graphify hook install reported success and wrote post-commit + post-checkout.

Steps to reproduce

  1. On Git for Windows, run graphify hook install in a repo with an existing graphify-out/.
  2. git commit (or pull a branch that fires post-checkout).
  3. Observe the rebuild log at ~/.cache/graphify-rebuild.log.

Expected

The graph rebuilds in the background and graph.json / GRAPH_REPORT.md update.

Actual

The log contains:

.git/hooks/post-commit: line 101: nohup: command not found

No rebuild happens. The commit/pull exits 0, so the user gets no signal that the graph is now stale. The same flaw is in the post-checkout hook.

Root cause

The hook templates use:

nohup "$GRAPHIFY_PYTHON" -c "...rebuild..." >> "$_GRAPHIFY_LOG" 2>&1 < /dev/null &
disown 2>/dev/null || true

nohup is a coreutils/util-linux tool that is absent from the minimal MSYS2 runtime Git for Windows bundles. setsid is also absent, so it isn't a drop-in substitute. There's no
package manager (pacman) in a stock Git for Windows install to add it either.

Suggested fix

graphify already requires Python, so let Python do the detaching instead of nohup/setsid — this is cross-platform and dependency-free. A tiny launcher spawns the real rebuild as
a fully detached process and returns immediately:

import os, sys, subprocess

cmd = [sys.executable, "-c", REBUILD_SRC]
kwargs = dict(stdout=open(LOG, "a", buffering=1),
              stderr=subprocess.STDOUT,
              stdin=subprocess.DEVNULL,
              cwd=os.getcwd(), close_fds=True)

if os.name == "nt":
    DETACHED_PROCESS = 0x00000008
    CREATE_NEW_PROCESS_GROUP = 0x00000200
    CREATE_BREAKAWAY_FROM_JOB = 0x01000000
    base = DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP
    try:
        subprocess.Popen(cmd, creationflags=base | CREATE_BREAKAWAY_FROM_JOB, **kwargs)
    except OSError:
        subprocess.Popen(cmd, creationflags=base, **kwargs)
else:
    subprocess.Popen(cmd, start_new_session=True, **kwargs)   # POSIX setsid equivalent

The hook then just runs "$GRAPHIFY_PYTHON" -c "$LAUNCHER" — no nohup, no &, returns instantly, and the detached child survives the hook (and its shell) exiting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions