Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
different-ai avatar

Sync Submodules

  • 2 installs
  • 29 repo stars
  • Updated March 27, 2026
  • different-ai/openwork-hub

Safely syncs a superproject and updates git submodules, handling dirty submodules like a modified Cargo.lock via per-repo stash.

About

Walks through inspecting dirty state, stashing inside a dirty submodule, pulling the root, and updating submodules to pinned commits. A developer uses it when submodule update fails or local changes would be overwritten by checkout.

  • Per-submodule stash before update (stashes are per-repo)
  • Full sync sequence: pull, submodule sync, update --init --recursive

Sync Submodules by the numbers

  • 2 all-time installs (skills.sh)
  • Ranked #498 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/different-ai/openwork-hub --skill sync-submodules

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs2
repo stars29
Last updatedMarch 27, 2026
Repositorydifferent-ai/openwork-hub

What it does

Safely syncs a superproject and updates git submodules, handling dirty submodules like a modified Cargo.lock via per-repo stash.

Files

SKILL.mdMarkdownGitHub ↗

Quick Usage (Already Configured)

1) See what is dirty (root + submodules)

date
git status --porcelain
git submodule foreach --recursive 'echo "--- $name ($path)"; git status --porcelain'

2) If a submodule is dirty, stash inside that submodule

Example for _repos/openwork when Cargo.lock blocks an update:

git -C _repos/openwork status --porcelain
git -C _repos/openwork stash push -u -m "wip: allow submodule update"

Notes:

  • Stashes are per-repo. You must run git stash in the submodule itself.
  • Use -u if untracked files exist.

3) Pull root + update submodules to the commits pinned by the root repo

git pull
git submodule sync --recursive
git submodule update --init --recursive
date

4) Re-apply the stash (optional)

Only do this if you actually want your local submodule changes back.

git -C _repos/openwork stash list
git -C _repos/openwork stash pop

Common Gotchas

  • error: Your local changes ... would be overwritten by checkout means the submodule has local changes and git submodule update is trying to move it to the commit pinned by the root repo.
  • Avoid git submodule foreach --recursive 'git pull' for normal syncing. Submodules are typically pinned to specific commits; pulling inside them can move them off the pinned commit and make the root repo look dirty.
  • If you intend to bump submodules to newer upstream commits, that is a different operation (it changes the root repo):
git submodule update --remote --recursive
git status

Submodule Pin Is Unreachable ("not our ref")

Symptom:

  • fatal: remote error: upload-pack: not our ref <sha> while fetching a submodule.

Meaning:

  • The root repo points at a submodule commit SHA that the submodule remote no longer advertises (history rewrite, deleted branch/tag, or missing permissions).

Fix (safe, local): 1. Pull root without touching submodules:

git pull --recurse-submodules=no

2. Move the submodule to a reachable ref (example uses origin/dev):

git -C _repos/<name> fetch origin --prune
git -C _repos/<name> checkout dev
git -C _repos/<name> pull --ff-only origin dev

3. Stage the gitlink in the root repo:

git add _repos/<name>
git status

Fix (proper, shared):

  • Open a PR that repins the submodule to a reachable commit and avoid force-pushing branches/tags that are used as submodule pins.

One-Liner Helper (Conservative)

This prints dirty submodules without changing anything:

git submodule foreach --recursive 'test -z "$(git status --porcelain)" || echo "DIRTY: $name ($path)"'

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.