Skip to content

fallow init --hooks scaffolds only dead-code against a single hard-coded base ref — what's the recommended setup for repos with multiple long-lived integration branches, and is fallow audit deliberately excluded from the hook? #242

@OmerGronich

Description

@OmerGronich

What happened?

Two related issues hit on a fresh fallow init --hooks against a Husky-using repo:

$ fallow init --hooks
Error: .husky/pre-commit already exists. Add the following line to your existing hook:

  fallow dead-code --changed-since <base> --fail-on-issues --quiet

1. Why only dead-code and not fallow audit?

crates/cli/src/init.rs hard-codes a single command in both the generated script and the "already exists" error message:

fallow dead-code --changed-since {base_ref} --fail-on-issues --quiet

But fallow audit already exists, takes --changed-since + --fail-on-issues, and bundles all three analyses (dead-code + dupes + health) into one verdict. Is audit deliberately excluded from pre-commit (too slow / too noisy on partial diffs?) or is this a doc/CLI gap? Either way, docs.fallow.tools/cli/init doesn't say.

2. The base ref is baked in at install time

The auto-detected (or --branch-supplied) ref is format!'d literally into the shell script:

fallow dead-code --changed-since main --fail-on-issues --quiet

That works for a feature → main topology. It breaks on any repo with multiple long-lived integration branches (next-release / hotfix / LTS), because the right base depends on which integration branch the feature targets — not on the global default sampled at hook-install time. Concrete failure modes:

  • Hotfix branched off a non-default integration branch → hook diffs against the wrong base, producing false positives (code "missing" on default) or false negatives.
  • No way to say "diff against the merge-base with my upstream" (git merge-base @{upstream} HEAD), which is the topology-agnostic answer.

Combined ask

  1. Document why dead-code (not audit) is the recommended pre-commit gate, or add --hooks-command audit.

  2. Have the generated hook resolve the base ref at commit time rather than baking it in, e.g.:

    UPSTREAM="$(git rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null || true)"
    BASE="${UPSTREAM#*/}"
    fallow dead-code --changed-since "${BASE:-main}" --fail-on-issues --quiet

Reproduction

mkdir -p /tmp/fallow-init-hooks-repro && cd /tmp/fallow-init-hooks-repro
git init -q && git -c user.email=a@b -c user.name=a commit --allow-empty -qm init
mkdir -p .husky && echo '#!/bin/sh' > .husky/pre-commit && chmod +x .husky/pre-commit

# 1. Hook installer only suggests dead-code, never audit:
fallow init --hooks
# => Error: .husky/pre-commit already exists. Add the following line ...
#      fallow dead-code --changed-since main --fail-on-issues --quiet

# 2. --branch is baked in literally; switching feature branches later doesn't change it:
rm .husky/pre-commit
fallow init --hooks --branch develop
grep fallow .husky/pre-commit
# => fallow dead-code --changed-since develop --fail-on-issues --quiet

Expected behavior

Either documented or implemented:

  • Doc explains the dead-code-vs-audit choice and the recommended setup for repos with multiple integration branches; or
  • fallow init --hooks resolves the base ref at hook execution time (e.g. via @{upstream}); or
  • fallow init --hooks --hooks-command audit opt-in to scaffold fallow audit instead of fallow dead-code.

Fallow version

2.56.0

Operating system

macOS

Configuration

No `.fallowrc.json` / `fallow.toml` is required to reproduce — the issue is in the hook scaffolder itself, not in analysis configuration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions