{"id":16406176,"url":"https://github.com/alerque/git-warp-time","last_synced_at":"2025-12-27T22:56:49.872Z","repository":{"id":40329956,"uuid":"355326893","full_name":"alerque/git-warp-time","owner":"alerque","description":"Rust library and CLI utility to reset timestamps of Git repository files to the time of the last modifying commit.","archived":false,"fork":false,"pushed_at":"2024-04-08T22:54:36.000Z","size":457,"stargazers_count":23,"open_issues_count":9,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-03T01:53:38.980Z","etag":null,"topics":["build-tools","filesystem","git","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alerque.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","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},"funding":{"github":["alerque"],"custom":["https://paypal.me/alerque"]}},"created_at":"2021-04-06T20:53:32.000Z","updated_at":"2024-07-20T00:20:41.675Z","dependencies_parsed_at":"2024-04-03T14:05:51.816Z","dependency_job_id":"6f68b6c9-b65f-482f-a760-11f7f09e6696","html_url":"https://github.com/alerque/git-warp-time","commit_stats":{"total_commits":120,"total_committers":1,"mean_commits":120.0,"dds":0.0,"last_synced_commit":"e743c9ab3f587ada01d8871f3cd5202dd8a6f2f4"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alerque%2Fgit-warp-time","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alerque%2Fgit-warp-time/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alerque%2Fgit-warp-time/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alerque%2Fgit-warp-time/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alerque","download_url":"https://codeload.github.com/alerque/git-warp-time/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243822295,"owners_count":20353500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["build-tools","filesystem","git","rust"],"created_at":"2024-10-11T06:08:53.010Z","updated_at":"2025-12-27T22:56:49.866Z","avatar_url":"https://github.com/alerque.png","language":"Rust","funding_links":["https://github.com/sponsors/alerque","https://paypal.me/alerque"],"categories":[],"sub_categories":[],"readme":"# git warp-time\n\n[![Rust Test Status](https://img.shields.io/github/actions/workflow/status/alerque/git-warp-time/rust_test.yml?branch=master\u0026label=Rust+Test\u0026logo=Rust)](https://github.com/alerque/git-warp-time/actions?workflow=Rust+Test)\n[![Rust Lint Status](https://img.shields.io/github/actions/workflow/status/alerque/git-warp-time/rust_lint.yml?branch=master\u0026label=Rust+Lint\u0026logo=Rust)](https://github.com/alerque/git-warp-time/actions?workflow=Rust+Lint)\n[![Docker Build Status](https://img.shields.io/github/actions/workflow/status/alerque/git-warp-time/deploy.yml?branch=master\u0026label=Docker%20Build\u0026logo=Docker)](https://github.com/alerque/git-warp-time/pkgs/container/git-warp-time)\n[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/alerque/git-warp-time?label=Tag\u0026logo=GitHub)](https://github.com/alerque/git-warp-time/releases)\n\nA CLI utility (and Rust library) that resets the timestamps of files in a Git repository working directory to the exact timestamp of the last commit which modified each file.\n\nFor use as a Rust library, include in your `Cargo.toml` as documented on the [crates.io listing](https://crates.io/crates/git-warp-time) and use per [the API documentation](https://docs.rs/git-warp-time).\n\n\u003ca href=\"https://repology.org/project/git-warp-time/versions\"\u003e\u003cimg src=\"https://repology.org/badge/vertical-allrepos/git-warp-time.svg\" align=\"right\" alt=\"Packaging status\"\u003e \u003c/a\u003e\nFor use as a CLI utility, first check whether your distro has packages (e.g. [Arch Linux](https://archlinux.org/packages/extra/x86_64/git-warp-time/)).\nOtherwise you can run this repository as a Nix Flake with `nix run github:alerque/git-warp-time`, install just plain binary with `cargo install git-warp-time`, or download the [latest](https://github.com/alerque/git-warp-time/releases/latest) source release and use `./configure; make; make install` for a full installation that includes autcompletion for Zsh, Bash, Fish, Elvish, and PowerShell.\n\n## CLI usage\n\nRun from inside any Git working directory after clone, after any checkout operation that switches branches, after rebases, etc.\n\n```console\n$ git clone ‹your project›\n$ cd ‹your project›\n$ git-warp-time\n```\n\nFor more usage see the `--help` output:\n\n```console\n$ git-warp-time --help\nCLI utility that resets the timestamps of files in a Git repository working\ndirectory to the exact timestamp of the last commit which modified each file\n\nUsage: git-warp-time [OPTIONS] [PATHS]...\n\nArguments:\n  [PATHS]...  Optional list of paths to operate on instead of default which is\n              all files tracked by Git\n\nOptions:\n  -d, --dirty         Include files tracked by Git but modifications in the\n                      working tee\n  -i, --ignored       Include files tracked by Git but also ignored\n  -o, --ignore-older  Only touch files that are newer than their history, ignore\n                      ones that are older\n  -q, --quiet         Don't print any output about files touched or skipped\n  -h, --help          Print help\n  -V, --version       Print version\n```\n\n## Library Usage\n\nIn your `Cargo.toml` file.\n\n```toml\n[dependencies]\ngit-warp-time = \"1.0\"\n```\n\nThen use the crate functions and types in your project something like this:\n\n```rust\nuse git_warp_time::{get_repo, reset_mtimes};\nuse git_warp_time::{FileSet, Options};\n\nlet repo = get_repo().unwrap();\nlet mut paths = FileSet::new();\npaths.insert(\"foo.txt\".into());\nlet mut opts = Options::new();\nopts.verbose(true).paths(Some(paths));\nlet files = reset_mtimes(repo, opts).unwrap();\nprintln!(\"Actioned files: {:?}\", files);\n```\n\n## CI Usage\n\nThis may me run in a CI workflow on almost any CI platform either as a binary or using the Docker container found in the GitHub Container Registry (`docker run ghcr.io/alerque/git-warp-time:latest`).\nIt is important to note that the Git repository needs to be checked out with depth.\nA shallow clone will cause all timestamps to be as new as the oldest commit in the clone, i.e. newer than actual.\n\nFor GitHub Actions this looks like so:\n\n```yaml\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - name: Git Warp Time\n        uses: alerque/git-warp-time@latest\n```\n\n# The story\n\nWhenever you `git clone` a project or `git checkout` a different branch, Git will write all the relevant files to your system at the moment you run the Git command.\nLogical enough.\nGit is doing the right thing.\nFor most use cases there is nothing wrong with the latest modification timestamp of a file to be the last time its state changed on your disk.\n\nHowever many build systems rely on file modification timestamps to understand when something needs to be rebuilt.\nGNU Make is one example that relies entirely on timestamps, but there are many others.\nA few rely on checksums (e.g. SCons) and keep a separate database of ‘last seen’ file states, but since this requires extra storage most build systems use what is available.\nWhat is available without the build system storing its own state is your file system's meta data.\n\nThe rub happens when you take advantage of Git's cheap branching model.\nMany workflows branch early and branch often.\nEvery time you `git checkout \u003cbranch\u003e`, your local working tree will be updated with the time of your checkout.\nIn some cases this will cause unnecessary rebuilds.\n\nFor many projects these rebuilds are required: if the state of all files at once doesn't match your project won't be built right.\nHowever for some projects, particularly those with multiple outputs, this might be a lot of wasted work.\n\n## A case study\n\nI have one project with many hundreds of LaTeX files.\nThe projects output is a directory of PDFs in a shared file repository (Nextcloud).\nThere are currently 5.7 Gigs of PDF files.\nEach week this collection grows.\nMost of the files are completely independent of each other, but they all use a common template and some other includes.\nMost weeks I just add new files and building the project just adds a few more files to the output.\nPeriodically I will change something in the template that will cause the entire output file set to regenerate.\nThat process takes about 20 hours to complete.\n\nGit is a distributed version control system and I *should* be able to work on this project from anywhere, but there is a problem.\nIf I clone the project to a new system, the source files are *all* newer than the existing outputs and the build system can't figure out what actually needs to be rebuilt.\nOne solution is to `touch` every file in the project after a clone with a very old date.\nThat sledge hammer approach works well enough for clones, but any time I work in a feature branch things get messed up.\nReturning from a feature branch that messes with the template to the master branch will cause the template file to be ‘new’ again and the whole project tries to rebuild.\nThis utility is a more elegant solution.\nRunning `git warp-time` after any clone, checkout, rebase, or similar operation will reset all the timestamps to when they were actually last touched by a commit.\n\nThe result is project portability.\nI can clone the project on a new system and without any build state data except the existing output files the project knows what it does and doesn't need to rebuild.\n\n## When not to use this\n\nNot all Git projects will benefit from `git warp-time`.\n\n* If your build system doesn't use timestamps, this won't help you.\n* If your project generates a single output such as a binary, you probably need to rebuild when *any* of the inputs change so this won't help much.\n* If your build system supports incremental builds and you do creative things in your branches, you might completely confuse your build system and cause incomplete builds.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falerque%2Fgit-warp-time","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falerque%2Fgit-warp-time","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falerque%2Fgit-warp-time/lists"}