Add --force to submodule update to prevent CI failures from dirty submodules
-
Please check this box if this contribution uses AI-generated content (including content generated by GitLab Duo features) as outlined in the GitLab DCO & CLA. As a benefit of being a GitLab Community Contributor, you receive complimentary access to GitLab Duo.
What does this MR do?
Adds the --force flag to the git submodule update --init command used by the GitLab Runner when preparing the repository during CI job execution.
This prevents failures caused by local changes within submodules, which result in errors like:
Your local changes to the following files would be overwritten by checkout
These errors can currently cause CI pipelines to fail when a submodule has been previously initialized and contains modified tracked files from a prior job or cached workspace.
Why is this needed?
Currently, the GitLab Runner attempts to clean submodules after the update has already failed (via git clean -ffdx and git reset --hard), but by then it’s too late. This MR resolves the issue proactively by discarding submodule changes during checkout, as expected in CI environments where build directories should be clean by default.
Why now?
When this behavior was first implemented (MR !704), Git 1.7.1 was still supported, and it did not allow --force on git submodule update.
As of GitLab Runner v16.0, the minimum supported Git version is 2.18.1, which fully supports --force on submodules. The original compatibility concern is no longer relevant.
What does this change?
-
The constructed command becomes:
git submodule update --init --force -
No change in submodule depth (i.e.,
--recursiveis not added in this MR) -
No behavioral change for users who expect top-level submodules only
Does this impact users?
-
✅ Prevents CI failures in projects using submodules -
✅ Safe and expected behavior for CI environments -
❌ No breaking changes -
❌ No changes to recursive behavior
Tests
Since this modifies a shell operation, functional behavior should remain the same except in dirty-submodule scenarios, which now succeed instead of failing. Manual test validation is recommended for repos using submodules.
Next steps / future ideas
- Optionally add support for
--recursiveas a follow-up, controlled by a CI variable or job setting - Improve documentation on how GitLab Runner handles submodules internally
Related issues
- !704 (merged) (original logic)