docs / guide / configuration
v0.12.0 linux · mac · windows
updated 0001-01-01 v0.12.0

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

FieldRequiredDescription
nameyesDescriptive name for the project. Must be unique across the file.
repositoryyesRemote 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_pathyesLocal 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_policynonever — 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.
branchesnoExtra local branches reported by status and fast-forwarded by pull (see Extra branches).
tagsnoList of free-form labels. Used by --tag filtering (see Tag filtering).
disablednotrue 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 / statusfull print 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: run gip fetch first to refresh them. Results appear as name@branch in the summary and JSON output. With --dirty extra branches are not reported.
  • gip pull fast-forwards each listed branch that is not checked out from its configured upstream (git fetch <remote> <upstream>:b). With --behind/--ahead the 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: never also 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 branches nothing 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:

  1. The path given by -f / --file flag
  2. The GIP_FILE environment variable
  3. .gip in the current working directory
  4. ~/.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 repository URL
  • 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 a local_path really 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-policy instead of pull_policy) stops gip before any command runs, so a typo cannot silently fall back to the default behaviour
  • duplicate name values 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
← Commands Getting Started →