Update git references in Nix flake files and Nix expressions.
nix-update-git detects outdated version tags and branch commits in flake inputs and fetcher calls, then updates them in place.
- Flake inputs: update
refvalues and inline?ref=in URL strings - Fetcher calls: update
rev,tag, andrefinfetchgit,fetchFromGitHub,fetchFromGitLab,fetchFromGitea,fetchFromForgejo,fetchFromCodeberg,fetchFromSourcehut,fetchFromBitbucket,fetchFromRepoOrCz,fetchFromGitiles,fetchpatch,fetchTarball, andbuiltins.fetchGit - mkDerivation: update
versionand corresponding source ref (tag/rev/ref) and hash instdenv.mkDerivation rec { ... }patterns - Derivation rules: additional rules for language-specific builders (
buildRustPackage,buildGoModule,buildPythonPackage, etc.) that follow the sameversion+srcpattern asmkDerivation; not enabled by default due to extra dependencies (e.g.cargoHash,vendorHash) - Branch following: use
# follow:branch <name>comments to track a branch's latest commit instead of version tags - Pinning:
# pincomments on any input or fetcher call skips it entirely - Multiple modes: check (default), update, and interactive
nix run github:yuxqiu/nix-update-gitOr add to your flake inputs:
inputs.nix-update-git.url = "github:yuxqiu/nix-update-git";cargo install --git https://github.com/yuxqiu/nix-update-gitRequires git on $PATH at runtime.
nix-update-git [OPTIONS] [FILES_OR_DIRECTORIES]...
Options:
-c, --check Check without making changes (default)
-u, --update Perform updates
-i, --interactive Confirm each update
-v, --verbose Enable verbose output
--format <FORMAT> Output format [default: text] [possible values: text, json]
-j, --jobs <N> Number of parallel file processing jobs [default: 4]
-r, --rules <RULES>... Rules to enable [default: fetcher flake mk-derivation]
-h, --help Print help
-V, --version Print version
nix-update-git flake.nix
# flake.nix: Found 1 update(s) from rule 'flake-input':
# - inputs.mylib.ref: v1.0.0 -> v2.0.0nix-update-git --update flake.nixnix-update-git flake.nix ./path/to/nix/nix-update-git --update --interactive flake.nixnix-update-git --format json flake.nixOutputs machine-readable JSON:
[
{
"file": "flake.nix",
"rule": "flake-input",
"field": "inputs.mylib.ref",
"old": "\"v1.0.0\"",
"new": "\"v2.0.0\"",
"range": [120, 128]
}
]Combine with --update to apply changes and get a JSON summary of what was updated.
nix-update-git uses rules to detect and apply updates. Each rule targets a specific pattern. By default, fetcher, flake, and mk-derivation are enabled. Additional derivation rules can be enabled via --rules:
# Enable buildRustPackage rule alongside defaults
nix-update-git --rules fetcher --rules flake --rules mk-derivation --rules build-rust-package file.nix
# Enable all rules
nix-update-git --rules all file.nix| Rule | Default | Nix function names | Description |
|---|---|---|---|
fetcher |
yes | — | Standalone fetcher calls (fetchgit, fetchFromGitHub, etc.) |
flake |
yes | — | Flake input URLs and refs |
mk-derivation |
yes | mkDerivation |
stdenv.mkDerivation rec { version = ...; src = fetchX { ... }; } |
build-rust-package |
no | buildRustPackage |
Rust packages (note: does not update cargoHash/cargoHash) |
build-go-module |
no | buildGoModule, buildGoPackage |
Go modules (note: does not update vendorHash) |
build-python-package |
no | buildPythonPackage, buildPythonApplication |
Python packages |
build-dune-package |
no | buildDunePackage |
OCaml/Dune packages |
build-npm-package |
no | buildNpmPackage |
Node.js packages |
build-mix-package |
no | buildMixPackage |
Elixir packages |
build-rebar3-release |
no | buildRebar3Release |
Erlang packages |
build-gem |
no | buildGem |
Ruby gems |
build-haskell-package |
no | buildHaskellPackage, mkHaskellPackage |
Haskell packages |
build-emscripten-package |
no | buildEmscriptenPackage |
Emscripten packages |
The fetcher rule never processes src = attributes inside any of the derivation-wrapper functions above — the derivation rules handle those exclusively. Enabling a derivation rule is needed for version updates in those patterns; the fetcher rule handles standalone fetcher calls regardless.
inputs.mylib = {
url = "github:owner/repo";
ref = "v1.0.0";
};inputs.mylib.url = "github:owner/repo?ref=v1.0.0";
# or
inputs.mylib = "git+https://example.com/repo.git?ref=v1.0.0";src = pkgs.fetchFromGitHub {
owner = "owner";
repo = "repo";
rev = "v1.0.0";
hash = "sha256-...";
};All standard nixpkgs fetchers are supported (fetchgit, fetchFromGitHub, fetchFromGitLab, fetchFromGitea, fetchFromForgejo, fetchFromCodeberg, fetchFromSourcehut, fetchFromBitbucket, fetchFromGitiles, fetchFromRepoOrCz, fetchpatch, fetchTarball, builtins.fetchGit).
mkDerivation updates version together with the source ref in src (priority: tag > rev > ref) and refreshes hash/sha256 when needed.
Supported source-ref behaviors:
- Pure version ref equal to
version(for examplerev = "v1.0.0") updates both together. - Pure commit-hash ref uses
versionto find newer upstream tags, then updatesversionand the ref. - Empty source ref can be populated from
version. - Interpolated source refs that depend on
${version}(inrecattrsets) updateversion; the interpolated ref text stays as-is. - Interpolated source refs that combine
${pname}and${version}(for examplerev = "${pname}-${version}") updateversion; the interpolated ref text stays as-is.
Fetcher attributes may also reference pname and other pure string attributes from the mkDerivation attrset via bare idents or string interpolation, when the attrset is rec or lambda-wrapped:
stdenv.mkDerivation rec {
pname = "my-package";
version = "1.0.0";
src = fetchFromGitHub {
owner = "my-org";
repo = pname; # bare ident
rev = "v${version}";
hash = "sha256-...";
};
};stdenv.mkDerivation (finalAttrs: {
pname = "my-package";
version = "1.0.0";
src = fetchFromGitHub {
owner = "${finalAttrs.pname}-org"; # dotted interpolation
repo = finalAttrs.pname; # bare ident
rev = "v${finalAttrs.version}";
hash = "sha256-...";
};
});Any pure string attribute (not just pname) from the mkDerivation attrset can be referenced this way. Without rec or a lambda wrapper, variable references in the fetcher are not resolved and the call is skipped.
stdenv.mkDerivation rec {
name = "foo-${version}";
version = "1.0.0";
src = fetchgit {
url = "https://github.com/owner/repo";
rev = "e67cc2e189679f991690ade03d0ee88566d2eb0f";
sha256 = "0nmyp5yrzl9dbq85wyiimsj9fklb8637a1936nw7zzvlnzkgh28n";
};
};When the # pin comment is present on the mkDerivation call, the entire block is skipped.
Use # follow:branch <name> to track a branch's latest commit instead of version tags:
src = fetchgit { # follow:branch master
url = "https://github.com/owner/repo";
rev = "e67cc2e189679f991690ade03d0ee88566d2eb0f";
hash = "sha256-...";
};The # follow: directive supports three modes:
| Mode | Syntax | Behavior |
|---|---|---|
| Branch | # follow:branch <name> |
Tracks the latest commit on the given branch |
| Regex | # follow:regex <pattern> |
Finds the latest tag matching ^<pattern>$ (full match) and resolves it to a SHA |
| Semver | # follow:semver <requirement> |
Finds the latest tag whose version (after stripping prefix like v) satisfies the semver requirement, and resolves it to a SHA |
Examples:
# Follow the main branch
src = fetchgit { # follow:branch main
url = "https://github.com/owner/repo";
rev = "0000000000000000000000000000000000000000";
hash = "sha256-...";
};
# Follow tags matching a regex (full match)
src = fetchgit { # follow:regex v[0-9]+\.[0-9]+\.[0-9]+
url = "https://github.com/owner/repo";
rev = "0000000000000000000000000000000000000000";
hash = "sha256-...";
};
# Follow tags within a semver range (prefix like 'v' is auto-stripped)
src = fetchFromGitHub { # follow:semver ^0.1
owner = "owner";
repo = "repo";
rev = "v0.1.0";
hash = "sha256-...";
};
# Only allow updates within 0.x
src = fetchFromGitHub { # follow:semver <1.0.0
owner = "owner";
repo = "repo";
rev = "v0.5.0";
hash = "sha256-...";
};
# fetchpatch also supports follow directives
patches = [ (fetchpatch { # follow:branch main
url = "https://github.com/owner/repo/commit/abc123.patch";
hash = "";
}) ];Any input or fetcher call with a # pin comment is skipped:
inputs.stable = { # pin
url = "github:owner/repo";
ref = "v1.0.0";
};src = fetchFromGitHub { # pin
owner = "owner";
repo = "repo";
rev = "v1.0.0";
hash = "sha256-...";
};| Type | Example |
|---|---|
| GitHub | github:owner/repo |
| GitLab | gitlab:owner/repo |
| SourceHut | sourcehut:~user/repo |
| Git HTTPS | git+https://example.com/repo.git |
| Git SSH | git+ssh://git@example.com/repo.git |
| Git local | git+file:///path/to/repo |
This project was inspired by update-nix-fetchgit, which provides similar functionality for updating fetcher calls.
The built-in nix-prefetch-git crate (nix-prefetch-git/) is a pure-Rust reimplementation of the shell-based nix-prefetch-git from nixpkgs. It replicates the same git clone, deterministic cleanup, and NAR hashing logic, removing the runtime dependency on the external nix-prefetch-git, nix-hash, and nix-store binaries.