30 个版本
0.8.3 | 2024年7月23日 |
---|---|
0.7.7 | 2024年5月27日 |
0.7.0 | 2023年12月9日 |
0.5.2 | 2023年11月3日 |
0.4.3 | 2021年4月16日 |
#74 in 构建工具
477 每月下载量
用于 casile
31KB
455 行
git warp-time
一个 CLI 工具(和 Rust 库),可以将 Git 仓库工作目录中文件的最后修改时间重置为最后修改每个文件的提交的确切时间戳。
作为 Rust 库使用时,请在您的 Cargo.toml
文件中包含它,并按照 crates.io 列表 中的说明使用,并按照 API 文档 使用。
作为 CLI 工具使用时,首先检查您的发行版是否有软件包(例如 Arch Linux)。否则,您可以使用 nix run github:alerque/git-warp-time
以 Nix Flake 运行此存储库,使用 cargo install git-warp-time
安装纯二进制文件,或下载最新的源代码版本并使用 ./configure; make; make install
进行完整安装,包括 Zsh、Bash、Fish、Elvish 和 PowerShell 的自动完成。
CLI 使用方法
在克隆后、任何切换分支的操作后、rebase 等,都可以在任何 Git 工作目录中运行。
$ git clone ‹your project›
$ cd ‹your project›
$ git-warp-time
有关更多信息,请参阅 --help
输出
$ git-warp-time --help
CLI utility that resets the timestamps of files in a Git repository working
directory to the exact timestamp of the last commit which modified each file
Usage: git-warp-time [OPTIONS] [PATHS]...
Arguments:
[PATHS]... Optional list of paths to operate on instead of default which is
all files tracked by Git
Options:
-d, --dirty Include files tracked by Git but modifications in the
working tee
-i, --ignored Include files tracked by Git but also ignored
-o, --ignore-older Only touch files that are newer than their history, ignore
ones that are older
-q, --quiet Don't print any output about files touched or skipped
-h, --help Print help
-V, --version Print version
库使用方法
在您的 Cargo.toml
文件中。
[dependencies]
git-warp-time = "0.8"
然后,在您的项目中使用类似以下方式使用 crate 函数和类型
use git_warp_time::{get_repo, reset_mtimes};
use git_warp_time::{FileSet, Options};
let repo = get_repo().unwrap();
let mut paths = FileSet::new();
paths.insert("foo.txt".into());
let mut opts = Options::new();
opts.verbose(true).paths(Some(paths));
let files = reset_mtimes(repo, opts).unwrap();
println!("Actioned files: {:?}", files);
CI 使用方法
该程序可以在几乎所有CI平台上运行,无论是作为二进制文件还是使用GitHub容器注册表中找到的Docker容器(docker run ghcr.io/alerque/git-warp-time:latest
)。需要注意的是,Git仓库必须以深度检出。浅克隆会导致所有时间戳都和新克隆的最早提交一样新,即比实际时间更晚。
对于GitHub Actions,看起来是这样的
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Git Warp Time
uses: alerque/git-warp-time:latest
情况概述
无论何时你使用git clone
克隆一个项目或使用git checkout
检出不同的分支,Git都会在运行Git命令的那一刻将所有相关文件写入你的系统。这是合乎逻辑的。Git正在做正确的事情。对于大多数用例,文件的最新修改时间戳与你在磁盘上更改其状态的时间相同是没有什么问题的。
然而,许多构建系统依赖于文件修改时间戳来理解何时需要重新构建。GNU Make就是一个完全依赖于时间戳的例子,但还有许多其他例子。一些依赖于校验和(例如SCons)并保持一个独立的“上次看到”的文件状态数据库,但由于这需要额外的存储空间,大多数构建系统都使用可用的资源。没有构建系统存储其自身状态的情况下,可用的资源是你的文件系统的元数据。
当你利用Git的低成本分叉模型时,问题就出现了。许多工作流程早期分叉并且频繁分叉。每次你使用git checkout <branch>
检查出一个分支时,你的本地工作树都会更新为检查出的时间。在某些情况下,这会导致不必要的重建。
对于许多项目,这些重建是必需的:如果所有文件的状态同时不匹配,项目将无法正确构建。然而,对于某些项目,尤其是具有多个输出的项目,这可能会造成大量的浪费工作。
案例研究
我有一个包含数百个LaTeX文件的项目。项目的输出是一个PDF文件的共享文件仓库(Nextcloud)中的目录。目前有5.7GB的PDF文件。每周这个集合都在增长。大多数文件之间完全独立,但它们都使用一个共同的模板和一些其他包含。大多数时候,我只是添加新的文件,构建项目只会添加一些输出文件。偶尔,我会修改模板,这将导致整个输出文件集重新生成。这个过程需要大约20小时才能完成。
Git是一个分布式版本控制系统,我应该能够从任何地方工作在这个项目上,但有一个问题。如果我将项目克隆到一个新的系统上,源文件都比现有的输出新,构建系统无法确定实际上需要重新构建什么。一个解决方案是在克隆后使用一个非常旧的日期对项目中的每个文件执行touch
。这种大锤式方法对于克隆来说效果很好,但每次我在功能分支上工作时,事情都会变得混乱。从修改模板的功能分支返回到主分支将导致模板文件再次被视为“新”的,整个项目将尝试重新构建。这个实用程序是一个更优雅的解决方案。在克隆、检出、rebase或类似操作之后运行git warp-time
将重置所有时间戳到它们最后一次被提交实际接触的时间。
结果是项目可移植性。我可以在新系统上克隆项目,除了现有的输出文件外,无需任何构建状态数据,项目就知道它做什么以及不需要重新构建。
何时不使用此功能
并非所有Git项目都能从git warp-time
中受益。
- 如果你的构建系统不使用时间戳,这不会帮到你。
- 如果你的项目生成单个输出,例如二进制文件,那么当任何输入改变时你可能需要重新构建,所以这不会有很大的帮助。
- 如果你的构建系统支持增量构建,你在分支中做了创新性的操作,你可能会完全混淆构建系统,导致构建不完整。
依赖项
~10–21MB
~386K SLoC