Markus Michalski FAQ

git-sync-all: Sync workflow

What git-sync-all does per repository: discovery, tags, commit with git add -A, pull, push, conflict detection, stash workflow, recovery and result states.

Deutsche Version

Back to overview

git-sync-all: Sync workflow

Finding repositories

The tool uses find to look for directories named .git down to depth SYNC_SCAN_DEPTH below each base directory. It then filters:

  1. Include filter: if SYNC_INCLUDE is set, the directory name must match one pattern.
  2. Exclude filter: if the directory name matches a pattern from SYNC_EXCLUDE, the repository is skipped.
  3. Remote check: a repository without a remote named SYNC_REMOTE is skipped silently (visible only with -v).

Only real .git directories count. Worktrees and submodules, where .git is a file, are not found. Nested repositories are treated as repositories of their own.

Per-repository flow

graph TD
    A[Repository] --> B[Fetch tags]
    B --> C[Check state and fetch remote]
    C --> D{Changes in working tree?}
    D -->|yes| E[Commit decision]
    D -->|no| F[Pull]
    E --> F
    F --> G[Push]
    G --> H[Result clean, synced, skipped or failed]

1. Tags

If tags are enabled, the tool runs git fetch --tags --prune-tags <remote>. Errors are ignored. The tool never pushes tags.

--prune-tags only removes local tags that the remote does not know when Git pruning is enabled as well (fetch.prune=true or remote.<name>.prune=true in your Git configuration). In that case locally created, not yet pushed tags are lost. Without such a setting the command only fetches new tags. With --no-tags or SYNC_TAGS=false the step is skipped entirely.

2. Check state

A repository is "dirty" when git status --porcelain prints anything. That includes untracked files. Unless --no-pull is set, the tool runs git fetch <remote> <branch> for the current branch and compares HEAD with the upstream (@{u}). If the branch has no upstream there is nothing to pull and nothing to push as far as the tool is concerned.

3. Changes in the working tree

Situation Behaviour
Dirty, remote has no new commits The tool shows up to 5 changed files and asks Commit and push changes? [y/n/q].
Dirty and remote has new commits The tool shows files and the number of new commits and lists files changed both locally and on the remote. Then the menu follows: c (commit), s (stash), k (skip), q (abort, see below).
Dirty with --no-commit, remote has new commits Automatic stash, pull, stash pop.
Dirty with --no-commit, remote unchanged No action.
Dirty with --no-pull Same as "remote has no new commits": plain commit prompt.

With --yes the prompt is skipped. When files overlap (changed locally and remotely), SYNC_CONFLICT_STRATEGY decides:

Strategy Effect in auto mode with overlapping files
skip The repository is skipped and counted as Skipped.
stash Stash, pull, stash pop. Changes stay uncommitted.
commit Commit and then pull, even if conflicts may arise.

Without overlapping files, auto mode always commits. Without a terminal and without --yes the repository is skipped.

If you answer q, the tool prints Aborted by user and ends only the handling of that repository. It counts as Failed, the remaining repositories are still processed, and the exit code is 1.

4. Commit

The commit consists of git add -A and git commit -m <message> -m <body>. git add -A stages all changes including untracked files, unless .gitignore excludes them. Commit hooks run as usual. Interactively you can override the message (Enter accepts the default). With --yes or without a terminal the template from SYNC_COMMIT_MSG is used.

5. Pull

If the upstream has new commits, the tool runs git pull --rebase <remote> <branch>, or git pull <remote> <branch> with SYNC_PULL_STRATEGY=merge. If the pull fails, the tool aborts a running rebase or merge itself (git rebase --abort or git merge --abort), prints the Git error indented and counts the repository as Failed. The repository stays in its state from before the pull.

6. Push

If the branch has commits ahead of the upstream, the tool runs git push <remote> <branch> without --force. If the push fails, the repository counts as Failed. The tool never switches branches and always works on the current one.

Stash workflow

git stash push --include-untracked, then pull, then git stash pop. If the pull fails, the stash is restored. If the pop has conflicts, the tool reports it and hints to resolve them and then run git stash drop. The repository then counts as Failed.

Results

Result Meaning
Clean Nothing to do.
Synced At least one action ran (commit, pull or push).
Skipped You chose n or k, or there was no terminal and no --yes.
Failed Commit, stash, pull or push failed, or you aborted with q. Leads to exit code 1.

A failure in one repository does not stop the run. The remaining repositories are still processed.