{"id":21857904,"url":"https://github.com/mathematic-inc/if-changed","last_synced_at":"2026-03-11T02:20:21.572Z","repository":{"id":234608477,"uuid":"788733183","full_name":"mathematic-inc/if-changed","owner":"mathematic-inc","description":"A pre-submit for file changes.","archived":false,"fork":false,"pushed_at":"2026-03-02T14:45:27.000Z","size":389,"stargazers_count":18,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-02T17:56:11.683Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mathematic-inc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"mathematic-inc"}},"created_at":"2024-04-19T01:19:48.000Z","updated_at":"2024-12-15T07:45:29.000Z","dependencies_parsed_at":"2024-04-20T02:39:21.860Z","dependency_job_id":"d0cdc448-3b31-429c-afa4-f74b7bcfbac2","html_url":"https://github.com/mathematic-inc/if-changed","commit_stats":null,"previous_names":["mathematic-inc/if-changed"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/mathematic-inc/if-changed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathematic-inc%2Fif-changed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathematic-inc%2Fif-changed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathematic-inc%2Fif-changed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathematic-inc%2Fif-changed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mathematic-inc","download_url":"https://codeload.github.com/mathematic-inc/if-changed/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathematic-inc%2Fif-changed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30367811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T02:33:16.163Z","updated_at":"2026-03-11T02:20:21.555Z","avatar_url":"https://github.com/mathematic-inc.png","language":"Rust","funding_links":["https://github.com/sponsors/mathematic-inc"],"categories":[],"sub_categories":[],"readme":"# `if-changed`\n\n[![crates.io](https://img.shields.io/crates/v/if-changed?style=flat-square)](https://crates.io/crates/if-changed)\n[![license](https://img.shields.io/crates/l/if-changed?style=flat-square)](https://github.com/mathematic-inc/if-changed)\n[![ci](https://img.shields.io/github/actions/workflow/status/mathematic-inc/if-changed/ci.yaml?label=ci\u0026style=flat-square)](https://github.com/mathematic-inc/if-changed/actions/workflows/ci.yaml)\n[![docs](https://img.shields.io/docsrs/if-changed?style=flat-square)](https://docs.rs/if-changed/latest/if_changed/index.html)\n\n`if-changed` is a command-line utility that checks for `\"if-changed\"` and `\"then-change\"` comments in a repository diff and errors if dependent files need changes.\n\n## Installation\n\n```bash\ncargo install if-changed\n```\n\n## Usage\n\n```bash\nUsage: if-changed [OPTIONS] [PATTERNS]...\n\nArguments:\n  [PATTERNS]...\n          Git patterns defining the set of files to check. By default, this will be all changed files between revisions.\n\n          This list follows the same rules as [`.gitignore`](https://git-scm.com/docs/gitignore) except relative paths/patterns are always matched against the repository root, even if the paths/patterns don't contain `/`. In particular, a leading `!` before a pattern will reinclude the pattern if it was excluded by a previous pattern.\n\nOptions:\n      --from-ref \u003cFROM_REF\u003e\n          The revision to compare against. By default, HEAD is used\n\n          [env: PRE_COMMIT_FROM_REF=]\n\n      --to-ref \u003cTO_REF\u003e\n          The revision to compare with. By default, the current working tree is used\n\n          [env: PRE_COMMIT_TO_REF=]\n\n  -h, --help\n          Print help (see a summary with '-h')\n\n  -V, --version\n          Print version\n```\n\nTo use with [`pre-commit`](https://pre-commit.com), add the following to your `.pre-commit-config.yaml`:\n\n```yaml\nrepos:\n  - repo: https://github.com/mathematic-inc/if-changed\n    rev: v0.3.2\n    hooks:\n      - id: if-changed\n```\n\n### Motivating example\n\nSuppose you have the following:\n\n```rs\n// lib.rs\nenum ErrorCode {\n    A,\n    B,\n    C,\n}\n```\n\n```ts\n// lib.ts\nconst enum ErrorCode {\n  A,\n  B,\n  C,\n}\n```\n\nTypically, to synchronize these enums, a common approach is to extract the enum values into a \"source-of-truth\" file. This often requires significant effort to generate the enums using the build system or a script, and to ensure everything works correctly. If the job is a one-off, the costs heavily outweigh the benefits.\n\nThis is where `if-changed` comes in. Instead of the above, suppose we have:\n\n```diff\n // lib.rs\n+// if-changed(ecrs)\n enum ErrorCode {\n     A,\n     B,\n     C,\n }\n+// then-change(lib.ts:ects)\n```\n\n```diff\n // lib.ts\n+// if-changed(ects)\n const enum ErrorCode {\n   A,\n   B,\n   C,\n }\n+// then-change(lib.rs:ecrs)\n```\n\nOnce this is commited, the next time `lib.rs` (or `lib.ts`) is changed in the lines surrounded by `\"if-changed\"` and `\"then-change\"`, `if-changed` will error if the other file (referenced in the `\"then-change\"` comment) does not have any changes in the corresponding named block.\n\n\u003e [!TIP]\n\u003e\n\u003e If you just want to assert that any change in a file is ok, then just reference the file without the name. For example,\n\u003e\n\u003e ```diff\n\u003e  // lib.ts\n\u003e  // if-changed(ects)\n\u003e  const enum ErrorCode {\n\u003e    A,\n\u003e    B,\n\u003e    C,\n\u003e  }\n\u003e -// then-change(lib.rs:ecrs)\n\u003e +// then-change(lib.rs)\n\u003e ```\n\n### File lists\n\nIf a block needs to specify several files, you can use commas and/or newlines to separate paths/patterns. For example,\n\n```c\n// then-change(foo/bar, baz)\n\n/// OR\n\n// then-change(\n//   foo/bar\n//   bar\n// )\n```\n\nThese lists follow the same rules as [`.gitignore`](https://git-scm.com/docs/gitignore), with the exception that relative paths/patterns are always matched against the file in which they are written, even if the paths/patterns don't contain `/`. Use a starting `/` to match the pattern against the repository root, e.g. `/*/bar`.\n\n### Long paths\n\nIf a path is too long, you can use a shell continuation `\\` to split it across multiple lines. For example, for the path `this/is/a/really/long/path/to/some/very/far/away/file`, you can do\n\n```c\n// then-change(\n//   this/is/a/really/long/path/to/some/very/far/ \\\n//   away/file\n// )\n```\n\n### Disabling `if-changed`\n\nTo disable `if-changed` for a specific file during a commit, add `Ignore-if-changed: \u003cpath\u003e, ... -- [REASON]` to the commit footer. Here, `\u003cpath\u003e` should be the file path. In general, `\u003cpath\u003e` can be any pattern allowed by [fnmatch](https://man7.org/linux/man-pages/man3/fnmatch.3.html).\n\n\u003e [!NOTE]\n\u003e\n\u003e If you want to disable `if-changed` when diffing the working tree, you can execute `if-changed` with the following:\n\u003e\n\u003e ```bash\n\u003e if-changed '*' !\u003cpath-or-pattern\u003e\n\u003e ```\n\u003e\n\u003e where `\u003cpath-or-pattern\u003e` is the path/pattern you want to ignore.\n\n## Contributing\n\nContributions to `if-changed` are welcome! Please submit a pull request or create an issue in the GitHub repository.\n\n\u003e This project is free and open-source work by a 501(c)(3) non-profit. If you find it useful, please consider [donating](https://github.com/sponsors/mathematic-inc).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathematic-inc%2Fif-changed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathematic-inc%2Fif-changed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathematic-inc%2Fif-changed/lists"}