Skip to content

Latest commit

 

History

History
115 lines (82 loc) · 3.94 KB

File metadata and controls

115 lines (82 loc) · 3.94 KB

Partial commit (+ drip)

gitty is a backup machine: commit + push as much as possible, every run.

  • paths that would block remote are held back locally; everything else goes through
  • built into gitty itself (not repo pre-commit/pre-push hooks)
  • drip-through on additive integrate: if resolvers clear some conflict paths and not others, commit the resolved subset; hold unresolved; do not park the whole merge (GITTY_PARTIAL=1 default)

Flow

git add -A
  → scan staged paths for offenders
  → unstage offenders (held back locally)
  → git commit
  → git push -f
  → if push rejects a file → unstage it, recommit, retry

What gets held back

Offender When Reason shown
Submodule gitlink (160000) Pre-commit scan submodule (use gittyembedded)
File over size limit Pre-commit scan exceeds push size limit (N bytes)
Push-rejected path After failed push push rejected
Pre-commit hook reject Elimination drip (GITTY_PARTIAL=1) catalog [CODE] reason or offender stderr

Default size limit: 100 MiB (GitHub hard limit)

  • Override with GITTY_MAX_FILE_BYTES

Hook elimination drip

When git commit fails under GITTY_PARTIAL=1 and more than one path is staged:

  1. snapshot hook stderr
  2. unstage each path in turn; retry commit on the remainder
  3. on success, hold the eliminated path with gitty_holdback_reason
  4. catalog (optional): .gitty/holdback-reasons.json or GITTY_HOLDBACK_CATALOG
    • rules[].match regex vs hook stderr → [code] reason (+ optional fix)
    • no catalog / no match → specific offender stderr + exit code (never mute pre-commit hook rejection)

Canonical test: tests/holdback-reason.smoke.sh

Ex

4 files modified

  • file1 is a 150 MiB blob
  • file2 is a submodule pointer
  • file3, file4 commit + push normally
    • held-back paths stay in your working tree unstaged
🟡 - Staging changes in /path/to/repo...
🔴 - huge.bin- held back (exceeds push size limit (500 bytes))
🟡 - 1 path(s) held back; proceeding with the rest
🟡 - Committing changes...
🟡 - Force pushing to remote...
── partial: commit/push ──
🟢 - ok.txt- committed and pushed
🟢 - fine.txt- committed and pushed
🔴 - huge.bin- not pushed (exceeds push size limit (500 bytes))
🟢 - partial success- 2 pushed, 1 held back
🟢 - Partial commit/push from /path/to/repo

Push retry

  • if a file slips past pre-scan (or the host rejects it for another size-related reason):
    • gitty parses push error → holds that path back → soft-resets the last commit → recommits without it → retries

Retries: GITTY_PUSH_RETRIES (default 8).

Canonical test

  • run: tests/partial-commit.smoke.sh
npm run test:partial
# or
tests/partial-commit.smoke.sh

Expects: huge.bin held back (🔴), ok.txt + fine.txt pushed (🟢), partial success dashboard

Integrate drip

On additive_git_integrate conflict:

  1. run .gitty/additive-resolvers.yaml classes
  2. if all conflict paths resolve → commit the merge
  3. if some resolve (GITTY_PARTIAL=1) → commit the resolved subset; hold the rest; report at end of run
  4. if none can land → park on bak/pending-merge-* (existing behavior)

Disable partial / drip

Old all-or-nothing behavior:

GITTY_PARTIAL=0 gitty "message" /path/to/repo

Submodule changes

  • gitty does not recurse into submodules
  • submodule pointer changes in parent are held back so parent push is not blocked
  • use gittyembedded when you intend to commit submodule work first → then parent

Large files with LFS

  • gitty does not configure Git LFS. For LFS-tracked patterns, use gittylfs

Rebase drip-through

On rebase conflict with remote (additive sync / stale-base autoheal), gitty holds back conflicting paths and commits+pushes the rest when GITTY_PARTIAL=1 (default). Hard-exits only if every path conflicts or GITTY_PARTIAL=0.