version-control — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited version-control (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use when designing or maintaining the shape of a repository's git history — choosing a branching model, deciding rebase vs merge, sizing commits, linking commits to tracker tickets, tagging releases, running parallel work across worktrees, and resolving the merge conflicts that arise from any of the above.
git commit --only -- <paths> discipline that prevents a parallel session from injecting unrelated staged files into your commitA repository's history is a decision log. When the log is noisy — merge commits where rebases would have been cleaner, multi-purpose commits that mix a fix with a feature, missing tracker IDs, branches that lived for a month — the team loses the ability to answer two questions that matter under pressure: "why did this change?" and "can I revert just this without taking everything else with it?" Both questions become archaeology rather than lookup.
The correct mental model is: every commit is a transaction the future will need to read, often in a hurry, often by someone who was not in the meeting. The discipline is to keep transactions small, attributed, and reversible. A commit that combines a refactor with a bug fix cannot be reverted cleanly when the fix turns out to be wrong; a commit without a tracker ID forces the next reader into git-blame archaeology to reconstruct intent.
The second principle is cost asymmetry. Cleaning up history before merge is cheap — squash, rebase, edit messages, split commits, all local operations on a feature branch. Cleaning up history after merge is expensive — it requires force-pushes, coordinated rewrites, and risks losing other people's work. Push the cleanup left to the moment the cost is lowest.
The third principle, specific to multi-agent and multi-session work: the git index is a process-shared mutex. Two agents in the same repo share .git/index, which means a git add in one session lands in the other session's git diff --cached. The standard git commit command picks up everything currently staged. The defence is path-limited commits (git commit --only -- <paths>) that build a temporary index from explicitly-named paths only, ignoring whatever else a parallel session has staged. Without this discipline, multi-agent work produces commits with surprise files.
Trunk-based development is the right default for almost every product codebase: a single long-lived branch (main), short-lived feature branches that integrate frequently (every 1-2 days), and incomplete features merged behind feature flags rather than parked on long-running branches.
| Rule | Why |
|---|---|
| Branches live < 48 hours | Forces small PRs, prevents drift from main, keeps merge cost low |
| PRs target < 400 changed lines | Larger PRs review poorly; reviewer attention drops sharply past 400 lines |
| Incomplete features ship behind flags | Lets you merge often without exposing half-built work to users |
main is always shippable | CI is the gate; nobody pushes broken code to main |
The anti-pattern is a long-lived develop branch (Git Flow) used as if it were trunk: drift accumulates, integration becomes its own project, and "merging develop to main" becomes a quarterly event with thousands of changed files. Git Flow exists for a different problem — shipping libraries with multiple supported major versions, where you genuinely need parallel release branches. If you are not maintaining v1.x and v2.x simultaneously, you do not need Git Flow.
A commit is "atomic" when reverting it produces no broken intermediate state, no accidentally-reverted unrelated work, and no half-finished features. The test:
If a senior reviewer asks "why does this commit exist?" and the answer requires the word "and," split the commit.
A commit titled "fix order rounding bug AND clean up the order utils file" is two commits. Run git rebase -i HEAD~1 and split before merging.
The commit-message wording (verb tense, prefix conventions, character limits) is naming — see naming-conventions for that. Version-control owns the commit boundaries: what counts as one commit, where one ends and the next begins, and whether the commit can stand alone if every later commit is reverted.
Every commit on a feature branch should link to the tracker ticket that produced it. The format is convention-driven; common forms:
feat(orders): add CSV export button (PROJ-1234)
Implements the export button on the order list. Output mirrors the
table columns; encoding is UTF-8 with BOM for spreadsheet compatibility.The tracker ID may live in the subject (visible in git log --oneline) or in a structured trailer (Refs: PROJ-1234, machine-parseable for automated cross-linking). Pick one and apply it consistently — mixing both fragments the searchable history.
If the change implements an architecture decision, reference the decision document in the commit body so future readers can find the why:
refactor(persistence): replace ad-hoc SQL with repository pattern (PROJ-1290)
Implements the data-access pattern decided in docs/decisions/0017-repository-pattern.md.
The change is mechanical; behavior is preserved by the existing integration tests.For feature-branch integration into main, prefer this order:
# Local workflow, on a feature branch
git fetch origin
git rebase origin/main # replay your commits on top of latest main
# resolve any conflicts, run tests, push
git push --force-with-lease # safe force: rejects if remote moved since your last fetch
# Merging the PR into main (in your forge UI or CLI)
# Pick "Squash and merge" if the branch has noisy WIP commits
# Pick "Rebase and merge" if every commit is publishable on its own
# Avoid "Create a merge commit" by default--force-with-lease is the safe variant of --force: it pushes only if the remote branch is at the SHA you last fetched, refusing if a collaborator pushed in between. Plain --force overwrites whatever is there, which destroys other people's work.
Releases are annotated tags (git tag -a), not lightweight tags. Annotated tags carry a tagger identity, a date, and a message — they are first-class objects in the git store and survive history rewrites that would orphan a lightweight tag.
git tag -a v1.2.0 -m "Release v1.2.0 — closes Milestone 4 (PROJ-MS-4)"
git push origin v1.2.0Tag names follow SemVer 2.0.0 (MAJOR.MINOR.PATCH, optional pre-release suffix -rc.1 or -beta.2). Patch tags are cheap; cut one per shipped fix.
When production has a bug that cannot wait for the next scheduled release:
# 1. Branch from the latest release tag, not from main
git checkout -b hotfix/v1.2.1 v1.2.0
# 2. Apply the minimal fix; test; commit
git commit -m "fix(orders): rounding error in tax calculation (PROJ-1305)"
# 3. Tag the patch
git tag -a v1.2.1 -m "Hotfix v1.2.1 — tax rounding (PROJ-1305)"
git push origin v1.2.1
# 4. Cherry-pick the fix back to main so the bug doesn't return next release
git checkout main
git cherry-pick <hotfix-commit-sha>
git push origin mainThe hotfix branch can be deleted after the cherry-pick. The discipline is to keep main's history linear and keep the hotfix tag pointing at the minimal fix, not at a snapshot of main.
Worktrees let multiple checkouts of the same repository coexist on different branches in different filesystem directories — without the cost of a full clone and without the conflict of a single working tree being on multiple branches.
# Create a worktree for a parallel feature
git worktree add ../my-repo-feature-A feature/A
# List current worktrees
git worktree list
# Remove a worktree after the work is merged
git worktree remove ../my-repo-feature-AWorktrees are essential when:
The cleanup discipline matters: an abandoned worktree directory does not free its branch lock; git worktree list --porcelain and git worktree prune are the cleanup tools.
In any repository where multiple processes or sessions share the working tree, the standard git commit is unsafe. The git index is a process-shared mutex; another session's git add lands in your git diff --cached, and a later git commit picks it up.
The defence:
# Right — for tracked files: build a temporary index from these paths only
git commit --only -m "..." -- path/one path/two
# Right — for new files: add first, then commit with --only
git add path/one path/two
git commit --only -m "..." -- path/one path/two
# Right — for multi-line messages: use -F with a temp file
printf 'subject\n\nbody\n' > /tmp/msg
git commit --only -F /tmp/msg -- path/one path/two
# Wrong — `-m` AFTER `--` is parsed as a pathspec, not a flag.
# git fails with: error: pathspec '-m' did not match any file(s) known to git
git commit --only -- path/one path/two -m "..."
# Wrong — picks up whatever a parallel session has staged
git add path/one
git commit -m "..."--only builds a transient index containing only the listed paths and commits from that. Whatever a parallel session has in the real index is left untouched for that session to commit. The safety window closes at the git commit --only call, not at the git add.
Flag ordering rule: Everything after -- is a path to git. Put -m, -F, and other flags BEFORE --, paths AFTER it. Both Tier 1 solvers in the 2026-05-18 post-v0.5.7 skill-graph cleanup hit the -m-after--- failure; Issue 3 worked around with -F /tmp/file.
After every commit, verify the file list:
git show --stat HEADIf files you did not intend to commit appeared, a parallel session staged them between your git add and your git commit. The recovery is git reset --soft HEAD^ and a retry with --only.
Conflicts come in two shapes:
Content conflicts — both sides edited the same lines. Resolution is line-by-line judgment, often informed by reading the surrounding context to understand what each side was trying to achieve.
Structural conflicts — one side renamed a file, moved a function, or changed a dependency boundary while the other side edited the old shape. Git frequently reports these as "added by us / deleted by them" or "modified by both" with surprising contents. The resolution is rarely a textual merge; it is a re-application of the smaller change against the new shape.
When a rebase produces conflicts on every replayed commit (a sign the branch and main have diverged structurally), the right move is often to abandon the rebase, recreate the branch from current main, and cherry-pick or re-author the changes:
git rebase --abort
git checkout main && git pull
git checkout -b feature/x-redo
# re-author the changes against the current main shapeA rebase that requires resolving the same conflict in five replayed commits is a signal — the branch is too old and the cleanup cost has crossed the recreate threshold.
Refs: trailer), enforced by hook or CI when feasiblegit commit --only -- <paths> to prevent parallel-session index contaminationgit push --force-with-lease is the only force-push form ever used; plain --force is treated as a destructive operation| Use instead | When |
|---|---|
naming-conventions | Writing the commit message itself (Conventional Commits prefix, scope, subject wording, identifier names) |
documentation | Drafting the contributor-docs page that explains your version-control policy |
code-review | Reviewing a PR's content for correctness, style, or design |
refactor | Reorganizing the code that the commits touch — version-control reorganizes the commits, refactor reorganizes the code |
debugging | Chasing a release-pipeline failure or a broken hotfix tag |
testing-strategy | Deciding whether a change to the branching policy itself needs a regression test |
<!-- skill-graph-context:start (generated — do not edit by hand) -->
Classification
software-engineering-methodtrueengineering/version-controlnaming-conventions), for chasing a release-pipeline failure (use debugging), or for reviewing a PR's content (use code-review).When to use
Not for
Related skills
code-reviewcode-review, refactor, naming-conventions, debugging, guardrailsKeywords
version control, git workflow, branching strategy, trunk-based development, git flow, short-lived branch, feature branch, merge vs rebase, linear history, atomic commit<!-- skill-graph-context:end -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.