Configuration
Config file format, project fields, tags, file lookup cascade, and validation warnings
File format
The config file is a list of project entries in YAML or JSON. Each entry describes one repository.
YAML example
- name: frontend
repository: "https://github.com/org/frontend.git"
local_path: ~/projects/frontend
tags: [work, js]
- name: dotfiles
repository: "git@github.com:user/dotfiles.git"
local_path: ~/dotfiles
tags: [personal]
- name: legacy
repository: "https://github.com/org/legacy.git"
local_path: ~/projects/legacy
pull_policy: never
JSON example
[
{
"name": "frontend",
"repository": "https://github.com/org/frontend.git",
"local_path": "~/projects/frontend",
"tags": ["work", "js"]
},
{
"name": "dotfiles",
"repository": "git@github.com:user/dotfiles.git",
"local_path": "~/dotfiles",
"tags": ["personal"]
}
]
Fields
| Field | Required | Description |
|---|---|---|
name | yes | Descriptive name for the project. Must be unique across the file. |
repository | yes | Remote URL (HTTPS or SSH). Used to clone missing repos (pull_policy: always or gip pull --all) and to detect the provider shown by list. |
local_path | yes | Local directory path. ~ and environment variables are expanded; an unset or empty variable is an error. A relative path is resolved against the directory of the configuration file, not the current directory. |
pull_policy | no | never — always skip this project for pull and fetch. always — clone via git clone if local_path does not exist. Omit for default behaviour: operate only on already-present directories. Values are case-insensitive. |
branches | no | Extra local branches reported by status and fast-forwarded by pull (see Extra branches). |
tags | no | List of free-form labels. Used by --tag filtering (see Tag filtering). |
disabled | no | true excludes the project from every command; gip list --all still shows it, marked (disabled). Default false. |
A project’s directory counts as present when it contains a .git entry; otherwise it is reported as missing ((missing) in tables, skipped by commands).
Extra branches
By default gip only looks at the branch currently checked out in each repo. List more with branches:
- name: api
repository: git@github.com:acme/api.git
local_path: ~/work/api
branches: [main, release/1.x]
gip status/statusfullprint one extra line per listed branch that is ahead, behind or without upstream (<path> [release/1.x] ↓2); branches in sync or not found locally are counted as skipped. It reads local refs only: rungip fetchfirst to refresh them. Results appear asname@branchin the summary and JSON output. With--dirtyextra branches are not reported.gip pullfast-forwards each listed branch that is not checked out from its configured upstream (git fetch <remote> <upstream>:b). With--behind/--aheadthe filter is evaluated on each listed branch’s own tracking state. Branches that cannot fast-forward (diverged) are reported as errors; local-only or ahead-only branches, missing branches and branches without upstream are skipped. Nothing is ever rewritten and the checked-out branch is never switched.pull_policy: neveralso disables branch updates. The checked-out branch keeps being handled by the normal pull.- The checked-out branch, empty names and names starting with
-are ignored (the latter two with a warning). - Without
branchesnothing changes.
Tag filtering
Tags allow you to run any gip command against a named subset of projects without maintaining separate config files.
Both YAML list syntaxes are accepted:
# inline (flow) syntax
- name: frontend
repository: "https://github.com/org/frontend.git"
local_path: ~/projects/frontend
tags: [work, js, client-acme]
# block (expanded) syntax
- name: infra
repository: "git@github.com:org/infra.git"
local_path: ~/work/infra
tags:
- work
- ops
# no tags — never selected by --tag
- name: dotfiles
repository: "git@github.com:user/dotfiles.git"
local_path: ~/dotfiles
A project with no tags key is never matched when --tag is active.
Use --tag with a comma-separated list, or repeat the flag, for OR logic:
# only repos tagged "work"
gip status --tag work
# OR: repos tagged "js" or "personal"
gip pull --tag js,personal
gip pull --tag js --tag personal # same
# combine with other flags
gip exec --tag work -j 8 -- make build
Matching is case-sensitive. --tag is available on every command except init and completion.
Config file lookup
gip searches for the config file in this order:
- The path given by
-f / --fileflag - The
GIP_FILEenvironment variable .gipin the current working directory~/.gip(home directory)
The first match wins. If GIP_FILE is set but points to a missing file gip stops with an error instead of falling back to the next location; if no file is found at all, gip stops with an error.
When the file was not given with -f, gip prints the one it uses on stderr (gip: using configuration <path>; suppressed by --quiet), so a .gip picked up from the current directory never goes unnoticed.
# explicit path
gip -f ~/work/gip.yaml status
# per-workspace config picked up automatically
cd ~/work && gip status
# override via environment variable
GIP_FILE=/tmp/test.yaml gip list
Validation warnings
When the config file is loaded, gip validates every entry and prints a warning for each anomaly before executing the command:
- missing or empty
name - missing or empty
local_path - unknown
pull_policy(accepted values:never,always) - invalid entry in
branches(empty or starting with-; it is ignored) - missing
repositoryURL - repository URL from which the provider cannot be detected
- leading or trailing spaces in a value (
name,repository,local_path,pull_policy,tags,branches): they are removed and the trimmed value is used. Only quoted YAML values can keep them; as a consequence alocal_pathreally ending with a space is not supported
These checks only read the file: gip check also compares the configuration with the disk and the remotes.
Warnings are printed on stderr in yellow and do not block execution. They are printed in --quiet and --json mode too; with --json they also appear in the warnings array of the output envelope.
Some problems are errors instead:
- an unknown key (for example
pull-policyinstead ofpull_policy) stops gip before any command runs, so a typo cannot silently fall back to the default behaviour - duplicate
namevalues stop gip before any command runs - a project with an empty
local_path, or one that uses an unset environment variable, is reported as an error for that project