Skip to content

Enhance dev-tools:sync to merge and normalize .gitignore entries from the dev-tools repository #12

@coisa

Description

@coisa

Description

Problem

dev-tools:sync already propagates shared repository conventions, but it does not currently ensure that consumer projects inherit the baseline .gitignore rules maintained in the dev-tools repository itself.

As a result:

  • projects may miss ignore patterns that are already considered standard by dev-tools
  • repositories can drift over time in what they ignore
  • developers may end up committing files that should have been consistently ignored across all consumers
  • .gitignore files can become unordered and harder to review or maintain

Proposal

Enhance dev-tools:sync so that it also synchronizes .gitignore entries from the dev-tools repository into the target project’s .gitignore.

The goal is to guarantee that anything ignored by dev-tools is also ignored by repositories that consume it, while still preserving project-specific entries.

Expected Behavior

When dev-tools:sync runs, it should:

  1. read the canonical .gitignore entries from the dev-tools repository
  2. read the target repository .gitignore, if it exists
  3. merge the entries without duplication
  4. preserve any project-specific rules already present
  5. write back a normalized .gitignore following a strict sort convention

Sorting / Formatting Rules

The resulting .gitignore should always be normalized using these rules:

1. Folders first

All directory entries, or directory-style wildcards, must come first.

Examples:

.idea/
.vscode/
backup/
public/
tmp/
vendor/
cache*/

2. Files second

All file entries, or file-style wildcards, must come after folders.

Examples:

.DS_Store
*.cache
composer.lock
TODO.md

3. Alphabetical order within each group

Inside each section, entries must be sorted alphabetically.

So the final file should look conceptually like:

[folders and directory wildcards, sorted]
[files and file wildcards, sorted]

Merge Semantics

Suggested behavior:

  • canonical dev-tools entries are always included
  • custom project entries are preserved
  • duplicates are removed
  • whitespace is normalized
  • optionally preserve comments only if they can remain attached deterministically to the relevant entry block

If comments make normalization significantly more complex, it would be acceptable for an initial version to prioritize correctness and deterministic ordering over comment preservation.

Example

If dev-tools has:

.idea/
.vscode/
vendor/
.DS_Store
*.cache

And a project has:

tmp/
vendor/
composer.lock

The synced result should be:

.idea/
.vscode/
tmp/
vendor/
*.cache
.DS_Store
composer.lock

The key requirement is deterministic grouping and alphabetical ordering.

Implementation Notes

A practical implementation could:

  • parse .gitignore line by line
  • discard blank lines
  • classify each non-comment entry as either:
    • directory / directory wildcard
    • file / file wildcard
    • merge all entries into a unique set
    • sort each category alphabetically
    • re-render the file in canonical order

Directory detection may be based on patterns such as:

  • trailing /
  • obvious directory wildcards intended for folders

File detection would cover everything else, including patterns like:

  • *.cache
  • .DS_Store
  • composer.lock

Requirements

  • dev-tools:sync must include the canonical ignore rules from dev-tools
  • project-specific rules must not be lost
  • duplicate entries must be removed
  • output must be deterministic
  • ordering must always be:
    1. folders / directory wildcards
    2. files / file wildcards
  • each section must be sorted alphabetically

Benefits

  • keeps ignore rules aligned across repositories
  • reduces accidental commits of generated/local files
  • improves consistency and maintainability
  • makes .gitignore diffs cleaner and more predictable
  • strengthens the role of dev-tools:sync as the source of shared repo conventions

Acceptance Criteria

  • dev-tools:sync must merge the canonical .gitignore entries from the dev-tools repository into the target project .gitignore.
  • Existing project-specific .gitignore entries must be preserved.
  • Duplicate entries must be removed.
  • The resulting .gitignore must be deterministic.
  • The resulting .gitignore must always be normalized with:
    • directory entries and directory-style wildcards first
    • file entries and file-style wildcards second
    • alphabetical ordering inside each group
  • Whitespace must be normalized consistently.
  • Comment preservation is optional for the initial implementation, but if comments are preserved, they must remain attached deterministically to the relevant entry block.
  • The core .gitignore synchronization logic must be isolated into distinct dedicated classes instead of being implemented directly inside the command.
  • Responsibilities must be clearly separated, for example:
    • one class for loading the canonical dev-tools ignore entries
    • one class for reading and parsing the target repository .gitignore
    • one class for classifying entries as directories or files
    • one class for merging, deduplicating, and sorting entries
    • one class for rendering and writing the normalized .gitignore
  • The command layer must act only as an orchestrator and must not contain the core normalization or merge rules.
  • The implementation must make it straightforward to extract the .gitignore synchronization logic into an external reusable package in the future, with minimal or no behavioral changes.
  • The core logic should avoid tight coupling to command-specific input/output APIs so it can later be reused by other commands, tools, or packages.

Additional Context

This would be especially useful for entries already standardized in dev-tools, such as editor folders, temporary directories, vendor artifacts, lock files, OS files, and wildcard cache patterns.

Today, these conventions can drift between repositories even when they should remain consistent.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions