Three statements were false against the git in use (2.39.5), each verified by
running it.
`git rebase --autosquash HEAD~N` without `-i` is a silent no-op: git prints
"Successfully rebased", the `fixup!` commit survives with the same SHA, and
rewrite-history.md presented that as the preferred flow with `-i` as an optional
review step. The agent reports the squash as done and the `fixup!` subject then
trips this repo's own commit-msg gate. `-i` is now the command, not the alternative.
"Fetch never modifies a local branch, so it is always safe to run" — new text on
this branch — is false: `git fetch origin main:probe` fast-forwarded the local
branch, and a `+` prefix force-updates it, losing commits. The claim is scoped to
the no-refspec form.
`git worktree add --orphan` does not exist before Git 2.42; on 2.39.5 it is
`error: unknown option 'orphan'`, exit 129. The same file gives a version floor for
`--recurse-submodules` three sections earlier. Floor added, with a fallback that
was tested before being documented.
git-workflow claimed "every request resolves to exactly one of these six" while
rebase, reset and stash were owned by no skill — `git reset` appeared nowhere in
the plugin, old tree or new — so "undo my last commit" routed nowhere. The claim is
gone, the router gains rows for all three, and the procedures now exist: plain
rebase with `--onto` and conflict handling, a reset mode table gated on `--hard`,
and stash save/pop/list/drop. `--hard` gets an always-loaded Gotcha, matching the
register the force-push refusal already sets.
Cherry-pick had three claimants pointing at git-history while git-commits owned the
flow, and the two copies were not equivalent — git-history's lacked the destination
check, the rtk prefix and `--abort`. Resolved to git-commits per #112; the weaker
duplicate is replaced by a hand-off.
git-commits' metadata.version was deleted rather than bumped in 14af50b, leaving two
house-contract documents citing a worked v0.1.2 to v0.1.3 transition against a file
declaring no version. Restored to 0.1.3.
Also: the divergent-pull explanation stated a `--ff-only` default that does not
exist (it is a hard error); `--remote` "requires" a configured branch where it uses
one; `git push origin --delete` moved to git-remotes, which owns the remote-side
gates; seven retired `git:<name>` source slugs; git-orchestrate quoted a
git-workflow sentence that no longer exists; git-submodules regains the indirect
trigger that made "add a dependency repo" routable; and commit atomicity is a common
gate rather than reachable only from the create flow.
Refs: #112, #113
3.6 KiB
topic, source_keys
| topic | source_keys | |
|---|---|---|
| submodules |
|
Adding, initializing, updating and pinning submodules
Clone a superproject that already has submodules
rtk git clone --recurse-submodules <url> # Git 2.13+, one step
# or, against an existing clone
rtk git submodule update --init --recursive
Add a dependency as a submodule
rtk git submodule add <url> <path>
rtk git commit -m "chore: add <name> as submodule"
add stages a .gitmodules entry and a gitlink — the commit is still required. Flags:
| Flag | Meaning |
|---|---|
-b <branch> |
Track a branch (submodule.<name>.branch) instead of only a pinned commit |
--depth <n> |
Shallow clone |
-f |
Force past a gitignored path or a name conflict |
--name <name> |
Logical name differing from the path |
Initialize without cloning
rtk git submodule init [<path>...] copies submodule URLs from .gitmodules into .git/config and
does nothing else. This is the point at which a local URL override can be edited before any fetch
happens. If a local mirror override is wanted, read references/urls-and-config.md before running
update. Use update --init to run both steps at once.
Update
rtk git submodule update --init --recursive is the common case: it clones what is missing and checks
out the commit the superproject recorded, in detached HEAD.
| Flag | Meaning |
|---|---|
--init |
Run init first, avoiding a separate step |
--remote |
Use the submodule's remote branch tip instead of the superproject's recorded commit |
--checkout |
Detached HEAD at the recorded commit (default) |
--rebase |
Rebase the current branch onto the recorded commit |
--merge |
Merge the recorded commit into the current branch |
--recursive |
Operate on nested submodules |
--jobs <n> |
Parallel clone (defaults to submodule.fetchJobs) |
-N / --no-fetch |
Skip the remote fetch |
-f |
Discard local changes in the submodule working tree |
--depth <n> |
Shallow clone |
--filter <spec> |
Partial clone filter |
Keep submodules pinned to the recorded commit
rtk git submodule update --recursive # after every rtk git pull
rtk git config submodule.recurse true # or do it automatically on pull/push/checkout
Move the pin forward to the tracked branch tip
rtk git submodule update --remote --merge --recursive
rtk git commit -am "chore: update submodules to latest"
--remote uses submodule.<name>.branch when it is set; without it Git falls back to the remote's
default branch. Commit the superproject afterwards or the new pin is lost on the next update.
Run one command across every submodule
rtk git submodule foreach --recursive '<command>'
rtk git submodule foreach 'git pull origin main || :' # || : continues past a failure
<command> runs inside each submodule's own working tree, so the git calls in it are the
submodule's own — that is the one place a bare git is correct. Append || : to keep the
traversal going instead of aborting at the first failure.
Git exports five shell variables into <command>. $sm_path and $displaypath name the same
directory from different vantage points and are not interchangeable:
| Variable | Meaning |
|---|---|
$name |
Logical submodule name (the .gitmodules section name, which need not match the path) |
$sm_path |
Path relative to the superproject root |
$displaypath |
Path relative to the current working directory |
$sha1 |
Commit SHA the superproject has recorded for this submodule |
$toplevel |
Absolute path of the superproject's root |