Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/Morrison-Lab/ai-config --skill configure-gitattributes명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
| name | configure-gitattributes |
| description | Configure file merge/diff attributes. |
| user-invocable | true |
| allowed-tools | ["Bash","Read","Edit","Write"] |
.gitattributes fixes a class of recurring annoyances at the git-mechanics
level instead of by hand each time: a changelog conflict resolved by an actual
human weighing two entries when git could have just kept both; a generated
directory that shows up in git diff --stat and language-detection stats as
if it were hand-written source; a shell script that silently gets CRLF line
endings and breaks bash -n. Reach for this skill any time a pattern of
conflict or noise traces back to how git treats one class of file, not just
once to fix the immediate instance.
cat .gitattributes 2>/dev/null || echo "no .gitattributes yet"
Append to it; don't overwrite existing lines you don't understand — ask if a line's purpose isn't obvious from context (a repo-specific export-ignore, a custom diff driver) rather than deleting it.
| Situation | Line | Why |
|---|---|---|
A running-log file where two branches each append their own entry and both should survive a merge (CHANGELOG.md ## Unreleased section, NEWS.md) | CHANGELOG.md merge=union | Git ships a built-in union low-level merge driver — no merge.<name>.driver config needed. On conflict it takes all lines from both sides instead of conflict-marking, in original order — it does not de-duplicate, so if both sides independently add the exact same single line it appears twice in the result. Standard in tidyverse-style R packages (NEWS.md merge=union) and widely used for CHANGELOG.md. Caveat: union merge has no understanding of section headers or ordering — it can leave two entries under the wrong heading, or a heading duplicated, if the sides diverged enough. Skim the merged file before pushing; it beats a conflict marker but isn't infallible. |
A file made of independent, multi-line blocks rather than single lines, where two branches each add a distinct block (BibTeX references.bib, one entry per block) | references.bib merge=union | Same built-in union driver as above, but with a sharper, opposite-direction caveat: when two branches each insert a whole new block at the same point in the file, and those blocks share an identical boundary line (e.g. the closing } every BibTeX entry ends with), the underlying line-based diff can misalign the two insertions and silently drop one copy of that shared line instead of duplicating it — producing corrupted content (mismatched braces) with no conflict raised. This is the opposite failure mode from the single-line case above (loss, not duplication) and only triggers when both insertions land at the same point in the file; insertions at genuinely different locations merge cleanly. Confirmed by local merge simulation on d-morrison/rme#989 / ucdavis/epi204#363. A render/validity CI check is a recommended backstop, not a guarantee — without one, silent corruption can reach main undetected. |
Shell scripts that could pick up CRLF (e.g. edited on Windows, or a tool re-writes them) and then fail bash -n with a cryptic EOF error | *.sh text eol=lf | Forces LF on checkout/commit regardless of the committer's platform. See , section , for the failure mode this prevents. |
For a merge-driver line, sanity-check it actually changed behavior rather than
trusting the .gitattributes edit alone:
git add .gitattributes && git commit -m "..." # COMMIT
# Simulate the conflict this was meant to prevent, e.g.:
git fetch origin main -q # FETCH
git merge origin/main # MERGE_BRANCH — should now auto-resolve where it previously conflicted
If a merge that used to need manual resolution now completes with
Auto-merging <file> and no conflict markers, the driver is working.
If the PR's rationale for keeping a risky merge=union attribute leans on
"CI will catch a corrupted result," verify that claim against the actual
workflow file — don't just assert it. Check the claimed job's trigger
paths: filter (or lack of one) actually covers the attributed file, and
that the job runs before merge (on: pull_request), not only after
(on: push to main). A stated backstop that doesn't actually fire on
the file in question is worse than no backstop claim at all — it creates
false confidence. (d-morrison/rme#989: the .gitattributes comment
claimed a Quarto render CI job would catch a malformed references.bib
before merge, but preview.yml's paths: filter excluded .bib entirely
— caught by review, fixed by adding the path.)
merge=union is a good default specifically for append-only log-style
files (changelogs, news files). It is a poor default for:
When in doubt, default to git's normal 3-way merge (i.e. don't add an attribute) and let a real conflict surface.
.gitattributes only. It does not touch .gitignore
(what's tracked at all) or CI config — those are separate concerns even
though they're often edited in the same session..gitattributes precedent in this corpus: shared/vendored/ and
_extensions/ directories in consumer repos are natural
linguist-vendored candidates; check whether the target repo already
attributes them before adding a duplicate line.mergeable_state API field reflect GitHub's own merge check, which does
not invoke merge=<driver> declarations. A merge GitHub reports as
conflicting can auto-resolve cleanly under a real local git merge that
honors .gitattributes (or the reverse). See
ultracode-merge-conflicts
for when this matters enough to verify with a real local merge instead of
trusting the platform's flag.memories/debugging.mdbash "syntax error: unexpected end of file" at last lineA directory whose contents are generated by a script from other source files in the repo (this repo's own codex-skills/, a compiled asset dir, a lockfile-derived output) | codex-skills/** linguist-generated | Tells GitHub's diff view to collapse it by default and excludes it from language-detection stats. Does not change git's merge/diff mechanics — pair with re-running the generator after merging main (see shared/workflow/sync-with-main.md's "conflict-free merge does not mean derived artifacts are in sync" note) rather than expecting this attribute to solve staleness. |
R package: NAMESPACE, regenerated by roxygen2::roxygenise() from @export/@import tags in R/*.R | NAMESPACE linguist-generated merge=union | linguist-generated for the diff/stats treatment; merge=union because two branches usually each add unrelated export()/import() lines — order rarely matters and a union merge avoids a conflict that devtools::document() would've resolved anyway by regenerating the file. Still re-run roxygen2::roxygenise() after merging (same staleness caveat as generated dirs above) — the union merge keeps the file mergeable, it doesn't keep it correct. |
R package: man/*.Rd, regenerated by roxygen2 from the same @export/doc tags | man/*.Rd linguist-generated | Diff/stats exclusion only — leave the merge driver unset. Unlike NAMESPACE's near-flat list of export lines, .Rd files have internal structure (sections, examples) where a union merge can interleave two incompatible edits to the same section. Regenerate with roxygen2 rather than merging by hand. |
Third-party code vendored into the repo (a copied library, _extensions/ Quarto filters) | _extensions/** linguist-vendored | Same diff/stats exclusion as linguist-generated, semantically for "not ours," not "derived from ours." |
| Binary files git might misdetect as text (images, PDFs already in the repo) | *.png binary, *.pdf binary | Prevents git from attempting a text diff/merge on binary content, which corrupts it. |
| A lockfile where line-level conflicts are common but the tool (not a human) should resolve them (rare — most lockfiles want the real conflict surfaced, not silently merged) | Usually leave unset | Don't reach for merge=union here by default — a union merge of renv.lock or package-lock.json can produce an inconsistent lockfile that installs cleanly but pins the wrong resolution. This row exists to name the anti-pattern, not recommend it. |
R package: DESCRIPTION, whose Version: field is the recurring merge-conflict hot spot when every PR bumps the dev version by hand | Never merge=union | DESCRIPTION is DCF (Debian Control File) format, one key: value per field --- a union merge of two conflicting Version: lines produces two Version: lines in the same stanza, which violates DCF's one-value-per-field rule --- but base R's read.dcf() does not error on it (verified: it silently keeps whichever Version: line comes last in the file). That is worse than a parse error, not better: nothing about the merged file looks broken, so the wrong version --- whichever side happened to sort last --- ships silently, with no parser complaint to catch it. This is not the lockfile row's "rare, tool-resolvable" case; it's a structural anti-pattern with no safe union-merge reading. The actual fix is to stop writing to the shared line at all: see Morrison-Lab/gha's bump-dev-version/version-check capabilities (added in gha#390, tracking issue gha#388), which auto-bump the dev version on main after every merge and invert version-check to fail a PR that touches Version: at all --- so no PR branch ever carries a competing value to conflict on. |
| Whole-repo default line-ending normalization | * text=auto eol=lf | Usually already present; check before assuming it's missing. |