Skip to main content

git-third-party

git-third-party

Vendor third-party git content into your repo as ordinary files — no submodules.

Three surfaces, one Go core: a git-third-party CLI, Python bindings (import git_third_party), and Node bindings (import { add, list, ... } from 'git-third-party'). All three speak the same third-party.toml / third-party.lock config and share the same cgo bridge for in-process calls.

third-party.toml records each entry's source URL, the ref it tracks, and any filters applied. third-party.lock pins the resolved commits. git-third-party update re-fetches upstream and stages the changes.

Why

Submodules need a second clone, complicate CI, and hide third-party code from grep, build, and IDE tooling. Subtree merges lose provenance. git-third-party keeps content in-tree and visible to every tool, with enough metadata to update in one command.

Requirements

  • git
  • Go 1.21+ (build only)

Install

CLI

Prebuilt binaries cover linux-x64, linux-arm64, darwin-x64, darwin-arm64, and win32-x64. Pick whichever package manager you already have:

# PyPI (wheel ships the binary as a pip script):
uv tool install git-third-party
pip install --user git-third-party

# npm (main package shells out to the platform-specific binary):
npm install -g git-third-party
pnpm add -g git-third-party

Build from source:

go build -o ~/.local/bin/git-third-party .

The binary's git- prefix lets you invoke it as either git-third-party or git third-party.

Python bindings

uv tool install git-third-party    # or pip install
from git_third_party import init, add, list_, version

print(version())
init()
add(dir="vendor/foo", url="https://github.com/x/y", follow="main")
for e in list_():
    print(e.dir, e.commit)

Mutating calls take dry_run= and commit_msg=. All calls take repo_path= (default .). Errors map to GitThirdPartyError and its subclasses (ConfigError, NetworkError, ConflictError, CheckDirtyError).

Node bindings

npm install git-third-party     # or pnpm/yarn add
import { init, add, list, version } from "git-third-party";

console.log(version());
init();
add({ dir: "vendor/foo", url: "https://github.com/x/y", follow: "main" });
for (const e of list()) {
  console.log(e.dir, e.commit);
}

ECMAScript Modules (ESM) only, ships TypeScript types, requires Node ≥ 18. Same options shape as the Python API; same error hierarchy. The bridge serializes calls process-wide — for parallel work, use worker_threads.

Quick start

Vendor a directory tracking a remote branch:

git-third-party add third_party/zlib https://github.com/madler/zlib --follow master
git commit -m "Vendor zlib"

Pull updates:

git-third-party update                    # all entries
git-third-party update third_party/zlib   # one entry
git-third-party status                    # dry-run
git commit -m "Update vendored zlib"

List, rename, remove:

git-third-party list
git-third-party rename third_party/zlib vendor/zlib
git-third-party remove third_party/zlib

Tracking a ref

Each entry tracks exactly one of:

  • --follow <branch> — track the branch tip, re-resolving on every update. Default when neither flag is set (resolved from the remote's HEAD).
  • --pin <tag-or-sha> — pin to a tag (resolved once, then cached) or a commit SHA (used as-is). 40-hex-char strings count as SHAs.

Switch with git-third-party set <dir> --pin v1.3.1 (or --follow master).

Filtering content

Vendor part of an upstream repo:

git-third-party add vendor/foo https://example.com/foo.git \
    --subdir src \
    --include '*.c' --include '*.h' \
    --exclude 'tests/'
  • --subdir — start from a subdirectory of the upstream repo.
  • --include — keep only matching paths (repeatable; default keeps everything).
  • --exclude — drop matching paths (repeatable; always wins over --include).

Patterns follow gitignore rules with documented deviations; see git-third-party add --help for the spec. Upstream submodules inline recursively unless excluded.

Configuration files

Two files live at the repo root, both committed:

  • third-party.toml — hand-editable intent. Each [[third_party]] table is one vendored directory. Each add/set/rename/remove rewrites the file, dropping any user comments.
  • third-party.lock — generated. Records the resolved commit and any saved tree-patch per entry. Sorted by dir for stable diffs. Do not edit by hand.

Example third-party.toml:

# git-third-party — vendored content config.

[[third_party]]
dir = "third_party/zlib"
url = "https://github.com/madler/zlib"
follow = "master"

[[third_party]]
dir = "vendor/foo"
url = "https://example.com/foo.git"
pin = "v1.3.1"
subdir = "src"
include = ["*.c", "*.h"]
exclude = ["tests/"]

Corresponding third-party.lock:

# git-third-party lockfile — generated; do not edit by hand.
version = 1

[[third_party]]
dir = "third_party/zlib"
commit = "abc123..."

[[third_party]]
dir = "vendor/foo"
commit = "def456..."

Commands

Command Aliases Purpose
init Create an empty third-party.toml (most users skip this — add creates it).
add DIR URL Register a new entry and download it.
set DIR … edit Change URL, ref, or filters for an existing entry.
unset DIR FIELD… Clear subdir, include, or exclude.
update [DIR] up Re-fetch and stage updates.
status [DIR] st update --dry-run.
list [DIR] ls Show entries and their tracking mode.
info DIR show Print full details for one entry.
rename DIR NEW_DIR mv Move a vendored directory and update the config.
remove DIR rm Unregister a directory and git rm -r its content.
patch save DIR (experimental) Record local edits as a tree-patch.
patch diff DIR (experimental) Show the saved tree-patch via git diff.
completion SHELL Print a bash/zsh/fish/powershell completion script.

Common flags

  • -v, -vv, -q — debug, trace, or warn-only logging.
  • --log-level=trace|debug|info|warn|error — explicit level.
  • --log-format=text|json — switch the stderr handler to JSON.
  • --color=auto|always|never — honors NO_COLOR.
  • --dry-run — plan without staging.
  • -f, --allow-dir-exists — let add/rename write into a non-empty target.
  • --profile <path> — write a CPU profile.
  • --json — emit a structured entryResult (or array) on stdout instead of human text. Schema lives in output.go.
  • --commit MSG — run git commit -m MSG after the command stages changes.
  • --check (on update/status) — exit non-zero if any entry would change. Useful in CI and pre-commit hooks.

Exit codes

Code Meaning
0 success
1 generic failure
2 configuration invalid (TOML parse, validation, lockfile schema mismatch)
3 network, fetch, or ref-resolution failure
4 unresolvable merge conflict during update
5 --check detected a pending change

Settings

Settings resolve through five layers, each overriding the previous:

  1. Built-in defaults.
  2. Per-user: git config --global third-party.<key>.
  3. Per-repo: a [settings] table in third-party.toml.
  4. Environment variables.
  5. CLI flags.

Environment variables:

  • GIT_THIRD_PARTY_LOG_LEVEL (trace/debug/info/warn/error) — same as --log-level.
  • GIT_THIRD_PARTY_LOG_FORMAT (text/json) — same as --log-format.
  • GIT_THIRD_PARTY_COLOR (auto/always/never) — same as --color.
  • GIT_THIRD_PARTY_EXPERIMENTAL — comma-separated feature names; same as --experimental.
  • NO_COLOR — standard cross-tool convention; disables ANSI color even when --color=auto.

Experimental commands (currently the patch subtree) need explicit opt-in: --experimental=patch (-Z patch), experimental = ["patch"] under [settings], or git config --global third-party.experimental patch.

Shell completions

# bash
source <(git-third-party completion bash)

# zsh
git-third-party completion zsh > "${fpath[1]}/_git-third-party"

# fish
git-third-party completion fish > ~/.config/fish/completions/git-third-party.fish

Editing vendored content (experimental)

Enable with --experimental=patch (or set the equivalent in [settings] or git-config — see Settings):

  • git-third-party --experimental=patch patch save <dir> — record local modifications as a tree-level patch in third-party.lock. The patch reapplies on every update via a 3-way merge.
  • git-third-party --experimental=patch patch diff <dir> — show the saved patch.

If update produces conflicts, git-third-party stores the patch with a -conflicts suffix; resolve with git add followed by another patch save. Review the resulting commits carefully — the feature is experimental for a reason.

License

MIT — see LICENSE.

Metadata

Release files for git-third-party 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for git-third-party 1.0.0
File
git_third_party-1.0.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 10.6 MB

Release files / git_third_party-1.0.0-py3-none-win_amd64.whl

Download URL git_third_party-1.0.0-py3-none-win_amd64.whl
Size 2.8 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
823d89b47bf470005aac491b6e4c1e1bb9d10e7f3675e95de210f5b19d96dd90
BLAKE2b-256 checksum
How to use checksums
556432a17c20da2fce5836d69c85301c74c472b0a2cb0d05df83969023648f79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release files / git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl

Download URL git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl
Size 2.7 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
9f12f997e885b65445a71858a61c93e1bbb305e537f5e6d3c4f76f24d219a204
BLAKE2b-256 checksum
How to use checksums
637a8e52c5669bd3771c2a49f11710f6174b196f6c71b252b8c48ffa28ceb958
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release files / git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl

Download URL git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl
Size 2.5 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
60f89b27fa61496a7ed4b324ddb9cdb935fd3772ad99203c9b025cb70cc02a38
BLAKE2b-256 checksum
How to use checksums
50f0c5621e066314b595fa06356f804d0f1b36a528051afc15729d16443d7a5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release files / git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl

Download URL git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl
Size 2.6 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
6ddd782157d61045a2bad53ae1059ba3166d8d1182e9daa02f27ba39f447542d
BLAKE2b-256 checksum
How to use checksums
d30d7caa1803c02a7426374c4b3d519061bfd1e144b6cc26ca0bd54691c0f127
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Security for git-third-party 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for git_third_party-1.0.0-py3-none-win_amd64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

4 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page