Vendor third-party Git repositories into your own, with path filtering and local patches.
Project description
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 everyupdate. Default when neither flag is set (resolved from the remote'sHEAD).--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. Eachadd/set/rename/removerewrites the file, dropping any user comments.third-party.lock— generated. Records the resolved commit and any savedtree-patchper entry. Sorted bydirfor 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— honorsNO_COLOR.--dry-run— plan without staging.-f,--allow-dir-exists— letadd/renamewrite into a non-empty target.--profile <path>— write a CPU profile.--json— emit a structuredentryResult(or array) on stdout instead of human text. Schema lives inoutput.go.--commit MSG— rungit commit -m MSGafter the command stages changes.--check(onupdate/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:
- Built-in defaults.
- Per-user:
git config --global third-party.<key>. - Per-repo: a
[settings]table inthird-party.toml. - Environment variables.
- 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 inthird-party.lock. The patch reapplies on everyupdatevia 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_third_party-1.0.0-py3-none-win_amd64.whl.
File metadata
- Download URL: git_third_party-1.0.0-py3-none-win_amd64.whl
- Upload date:
- Size: 2.8 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
823d89b47bf470005aac491b6e4c1e1bb9d10e7f3675e95de210f5b19d96dd90
|
|
| MD5 |
1b26e9a27646d22d0786fa187bd55626
|
|
| BLAKE2b-256 |
556432a17c20da2fce5836d69c85301c74c472b0a2cb0d05df83969023648f79
|
Provenance
The following attestation bundles were made for git_third_party-1.0.0-py3-none-win_amd64.whl:
Publisher:
release.yml on khwstolle/git-third-party
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_third_party-1.0.0-py3-none-win_amd64.whl -
Subject digest:
823d89b47bf470005aac491b6e4c1e1bb9d10e7f3675e95de210f5b19d96dd90 - Sigstore transparency entry: 1523901862
- Sigstore integration time:
-
Permalink:
khwstolle/git-third-party@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/khwstolle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Trigger Event:
push
-
Statement type:
File details
Details for the file git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl.
File metadata
- Download URL: git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl
- Upload date:
- Size: 2.7 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f12f997e885b65445a71858a61c93e1bbb305e537f5e6d3c4f76f24d219a204
|
|
| MD5 |
0d863d818a3baad365f63a8f5ad9ff7c
|
|
| BLAKE2b-256 |
637a8e52c5669bd3771c2a49f11710f6174b196f6c71b252b8c48ffa28ceb958
|
Provenance
The following attestation bundles were made for git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl:
Publisher:
release.yml on khwstolle/git-third-party
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_third_party-1.0.0-py3-none-manylinux2014_x86_64.whl -
Subject digest:
9f12f997e885b65445a71858a61c93e1bbb305e537f5e6d3c4f76f24d219a204 - Sigstore transparency entry: 1523901665
- Sigstore integration time:
-
Permalink:
khwstolle/git-third-party@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/khwstolle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Trigger Event:
push
-
Statement type:
File details
Details for the file git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl.
File metadata
- Download URL: git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl
- Upload date:
- Size: 2.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60f89b27fa61496a7ed4b324ddb9cdb935fd3772ad99203c9b025cb70cc02a38
|
|
| MD5 |
a3ad611ecf4cbd446fb427c057f5d827
|
|
| BLAKE2b-256 |
50f0c5621e066314b595fa06356f804d0f1b36a528051afc15729d16443d7a5f
|
Provenance
The following attestation bundles were made for git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl:
Publisher:
release.yml on khwstolle/git-third-party
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_third_party-1.0.0-py3-none-manylinux2014_aarch64.whl -
Subject digest:
60f89b27fa61496a7ed4b324ddb9cdb935fd3772ad99203c9b025cb70cc02a38 - Sigstore transparency entry: 1523901781
- Sigstore integration time:
-
Permalink:
khwstolle/git-third-party@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/khwstolle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Trigger Event:
push
-
Statement type:
File details
Details for the file git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.6 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ddd782157d61045a2bad53ae1059ba3166d8d1182e9daa02f27ba39f447542d
|
|
| MD5 |
fb4247cbe6212dae74b803fb575d1165
|
|
| BLAKE2b-256 |
d30d7caa1803c02a7426374c4b3d519061bfd1e144b6cc26ca0bd54691c0f127
|
Provenance
The following attestation bundles were made for git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on khwstolle/git-third-party
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_third_party-1.0.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
6ddd782157d61045a2bad53ae1059ba3166d8d1182e9daa02f27ba39f447542d - Sigstore transparency entry: 1523901598
- Sigstore integration time:
-
Permalink:
khwstolle/git-third-party@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/khwstolle
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b583b5a061f42ba87961d504c65d5ae613f32c73 -
Trigger Event:
push
-
Statement type: