Skip to content

Docs: troubleshooting entry for copier template drift (update is delta-based, files silently diverge) #232

Description

@gilesknap

What

Add a Troubleshooting entry explaining a copier-specific failure mode we keep hitting when updating services repos from services-template-helm (and other copier templates): a template-managed file silently diverges from the template and copier update never heals it, even though .copier-answers.yml reports the latest _commit.

Why it matters

This is genuinely insidious — it cost real debugging time. Symptoms:

  • .copier-answers.yml says _commit: is the latest template revision, so the repo looks up to date.
  • A scaffolding file (e.g. ci_verify.sh, .pre-commit-config.yaml, renovate.json) still contains an old version that matches no current template revision.
  • No .rej files and no inline conflict markers are left behind, so nothing flags the problem.

Root cause (worth stating in the docs)

copier update is a 3-way merge, not a re-render. It regenerates the template at your old _commit, diffs it against the new _commit, and replays only that diff onto your files. Consequences:

  • If a file diverges once (a botched merge, a hand-edit, or a merge git considers "clean" but applies to the wrong context) and the template later stops changing that file, no future delta is ever generated for it. copier update will never touch it again.
  • Mental model to teach: update syncs changes, not state. Being on the latest _commit does not guarantee your files match a clean render.

Suggested docs content

Diagnostic — "am I actually in sync with the template?" (non-destructive, runs on a throwaway clone):

tmp=$(mktemp -d); git clone --quiet . "$tmp" && cd "$tmp"
copier recopy -f --skip-tasks      # re-render pristine from your recorded answers
git diff --stat                    # ANY template-managed file here = drift
  • Empty → genuinely in sync.
  • Non-empty → exactly the files that have drifted (minus intentional local customizations, which you eyeball).

Fix — force a clean re-render with copier recopy:

copier recopy --pretend -f    # preview what would be overwritten
copier recopy -f              # -f == --defaults --overwrite ; apply
git diff                      # review; keep intentional edits, discard drift

Run it on a committed tree so git diff is your safety net. Service instance content (e.g. services/*) is not template-managed and is left untouched; only scaffolding is reset.

Prevention for routine updates:

  • copier update --conflict rej → failed hunks become visible .rej files instead of silent inline merges.
  • copier update --pretend → preview before applying.
  • Always update on a clean git tree and review the resulting diff — a suspiciously small diff for a release that changed scaffolding is a red flag.
  • Periodically run the recopy-diff diagnostic above, not just update.

Caveats to mention:

  • _skip_if_exists in copier.yml: listed files are never overwritten by copy/recopy, so recopy won't heal them either — they must be fixed by hand.
  • recopy re-runs _tasks/migrations — use --skip-tasks for a pure file diff, and --trust only if the template needs unsafe features.

Placement

A new entry under the Troubleshooting section of the docs (alongside the existing ibek / services-repo guidance). Verified against copier 9.11.3.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions