Title says it all. I tried using a bunch of different git commands like git submodule update --remote --merge
and git submodule foreach git pull origin master
which work fine on my computer, but not when it's run on GitHub actions.
I tried adding git status
to the workflow and the status just shows "Up to date with origin/master, nothing to commit" or something like that.

- 445
- 1
- 4
- 9
-
Did you end up solving this @ma1234 – pratikpc Jan 26 '21 at 20:18
-
2No, I just abandoned submodules and instead used a GitHub Action to just copy over the files normally. – ma1234 Jan 26 '21 at 21:57
8 Answers
If you need to auto update references to your submodules via GitHub actions:
Create a new workflow in your parent repository that will synchronize references:
name: 'Submodules Sync'
on:
# Allows you to run this workflow manually from the Actions tab or through HTTP API
workflow_dispatch:
jobs:
sync:
name: 'Submodules Sync'
runs-on: ubuntu-latest
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.CI_TOKEN }}
submodules: true
# Update references
- name: Git Sumbodule Update
run: |
git pull --recurse-submodules
git submodule update --remote --recursive
- name: Commit update
run: |
git config --global user.name 'Git bot'
git config --global user.email 'bot@noreply.github.com'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git commit -am "Auto updated submodule references" && git push || echo "No changes to commit"
where
- CI_TOKEN is a security token variable in GitHub that have 'Read-Write' access to the parent repository, and 'Read' access to submodule repositories.
In the child (submodule) GitHub action notify the parent about changes.
name: 'Submodule Notify Parent'
on:
push:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
notify:
name: 'Submodule Notify Parent'
runs-on: ubuntu-latest
# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
steps:
- name: Github REST API Call
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
PARENT_REPO: <my_organization/my-app>
PARENT_BRANCH: develop
WORKFLOW_ID: <9999999>
run: |
curl -fL --retry 3 -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ env.CI_TOKEN }}" https://api.github.com/repos/${{ env.PARENT_REPO }}/actions/workflows/${{ env.WORKFLOW_ID }}/dispatches -d '{"ref":"${{ env.PARENT_BRANCH }}"}'
where
- PARENT_REPO - name of the parent repository as it is in Github (my_org/my_app or just my_app if there is no organization).
- WORKFLOW_ID - parent Wofklow ID to call via rest API. To find it run curl using your
CI_TOKEN
:curl -X GET -H "Authorization: token $CI_TOKEN" https://api.github.com/repos/$PARENT_REPO/actions/workflows
Repeat the workflow creation for every submodule.
P.S. For me it works very stable. Please add information about existing github actions with the above logic if there is any.

- 7,115
- 57
- 60
-
If you had no way to run workflows on the submodule, could you just run the first workflow on a schedule? – ma1234 Apr 12 '21 at 21:50
-
2Hi @ma1234, yes, it is possible to set up a schedule for workflow run, please refer to https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events Though in this case there will be time intervals when the parent branch is out of sync with submodule references. – Artur A Apr 13 '21 at 01:42
A much better option today is to utilize Dependabot to auto create PRs for submodules.
A sample that checks daily if a submodule has been updated:
In .github/dependabot.yml
version: 2
updates:
- package-ecosystem: gitsubmodule
schedule:
interval: "daily"
directory: /

- 3,602
- 20
- 33
You can achieve this with a single action in the submodule repository:
name: Send submodule updates to parent repo
on:
push:
branches:
- main
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
repository: org/parent_repository
token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}
submodules: true
- name: Pull & update submodules recursively
run: |
git submodule update --init --recursive
git submodule update --recursive --remote
- name: Commit
run: |
git config user.email "actions@github.com"
git config user.name "GitHub Actions - update submodules"
git add --all
git commit -m "Update submodules" || echo "No changes to commit"
git push
You need to:
- adjust the name of the parent repository (here, I used
org/parent_repository
as an example). - create a private access token. with sufficient permissions to write in your parent repository and save it as a repository secret (under the name
PRIVATE_TOKEN_GITHUB
in my example above)
With this action, every push on the main
branch in the submodule repository will result in a commit pulling the update in the parent repository.

- 834
- 7
- 15

- 935
- 9
- 12
-
2
-
Doesn't it kind of suck to have this global personal access token in this workflow @Droplet? – Eric Carmichael Sep 11 '22 at 22:01
-
@EricCarmichael, it's a tough question, especially when framed so generally. Depends on your threat model. I can give two general answers, which may or may not apply well to your specific case: 1. It is generally considered safer/better practice to use the built-in GITHUB_TOKEN PAT **when possible** because it has restricted permissions & scope (but we don't have this option here). 2. It would be ideal if GitHub allowed us to create PAT with permissions linked to a specific repo, instead of all your repos. – Droplet Sep 12 '22 at 09:40
-
Regarding my second point, this answer https://stackoverflow.com/a/63296569/4439357 seems to propose an interesting alternative: use a deploy key instead of a PAT. I'll have a look and update my answer if it works. Thanks! – Droplet Sep 12 '22 at 09:41
-
Another possible answer: I didn't mention it but in my organisation, we have a dedicated machine user (https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users) and we use its PAT for automation. In the worst case scenario, where someone steals the PAT, the damage is more limited – Droplet Sep 12 '22 at 10:25
-
1@Droplet thanks for all of the info! So a "Deploy key" can make commits and such? – Eric Carmichael Sep 13 '22 at 17:18
-
Action runs successfully but the submodule is not updated. Shouldn't the step `git submodule update --recursive --remote` run on the parent repo? when i run this directly in the parent repo it updated the submodule. Should the PRIVATE_TOKEN be present in both repos? Thanks! – Ilir Jun 16 '23 at 12:28
-
Yes, the `git submodule update` step has to run in the parent repo. But this is already the case if you set the "repository" option value correctly in the `actions/checkout` step, as documented in the answer. The `PRIVATE_TOKEN` needs write access to the parent repo but should be in the secrets of the submodule repo, where this workflow lives. – Droplet Jun 19 '23 at 15:13
Simple solution
You pull and update the submodules recursively and then commit to the repo.
name: Update submodules
# Controls when the action will run.
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
# This workflow contains a single job called "update"
update:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Pull & update submodules recursively
run: |
git submodule update --init --recursive
git submodule update --recursive --remote
- name: Commit & push changes
run: |
git config --global user.name ${{ secrets.USER_NAME }}
git config --global user.email ${{ secrets.USER_EMAIL }}
git commit -am "Update submodules"
git push
Instead of using Github secrets like ${{ secrets.USER_NAME }}
I just hard code my git credentials since I'm lazy, but I figured you might care about security.

- 749
- 7
- 17
i try this it working for me
- uses: actions/checkout@v3
with:
repository: {owner}/repo
token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}
submodules: recursive
- name: submodules recursively
run: git submodule update --init --recursive

- 11
- 1
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 22 '22 at 08:03
You can compare your GitHub Action source with one like submodule-branch-check
, which does make at least a git submodule update
.
Check if the update --remote
is enough to pull from its own remote origin.

- 1,262,500
- 529
- 4,410
- 5,250
it working for me, read acticle in here https://zenn.dev/ymmmtym/articles/dc741561759a49
name: Update submodules
on:
push:
branches:
- dev
pull_request:
branches:
- dev
jobs:
update_submodules:
name: Update submodules
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
token : ${{secrets.OOG_TOKEN}}
submodules : true
- name: Update submodules
id: update
run: git submodule update --remote --recursive
- name: Run git status
id: status
run: echo "::set-output name=status::$(git status -s)"
- name: Add and commit files
run: |
git add .
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -m "Update submodules at $(date "+DATE: %Y-%m-%d TIME: %H:%M:%S")"
if: ${{ steps.status.outputs.status }}
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: dev
if: ${{ steps.status.outputs.status && github.event_name == 'push' }}

- 33
- 5
-
1Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 22 '22 at 10:08
I was able to implement @Droplet's solution! I extended it to update multiple parent repos that are using the submodule using a matrix like so:
on:
push:
branches:
- master
jobs:
update_parent_repos:
runs-on: ubuntu-latest
strategy:
matrix:
parent_repo: [parent_repo_1, parent_repo_2]
steps:
- uses: actions/checkout@v3
with:
repository: myriadgenetics/${{ matrix.parent_repo }}
token: ${{ secrets.ACTIONS_TOKEN }}
submodules: 'recursive'
- name: Pull & update submodules recursively
run: |
git submodule update --init --recursive
git submodule update --recursive --remote
- name: Commit
run: |
git config user.email "actions@github.com"
git config user.name "GitHub Actions - update submodules"
git add --all
git commit -m "Update submodules" || echo "No changes to commit"
git push
You will have to use the correct label for the action runner for your use case if it isn't ubuntu-latest
, update parent_repo_1
and parent_repo_2
to the names of the parent repos you want to update the submodule in, and use the correct token name for your use case. I for some reason had to include submodules: 'recursive'
otherwise was running into issues when running the commands within "Pull & update submodules recursively".

- 31
- 1
- 2