GitPython: how to commit updated submodule
Asked Answered
P

1

12

I have been at this for hours now, and although I have a feeling I'm close I can't seem to figure this out.

I'm trying to make a script that takes a git repository, updates a submodule in that repository to a specified version, and commits that change.

What works:

I can find the repository, get the submodule and check out the commit I want.

What doesn't work:

I can't seem to add the updated submodule hash so I can commit it.

My Code:

repos = Repo('path/to/repos')
submodule = repos.submodule('submodule-name')
submodule.module().git.checkout('wanted commit')

diff = repos.index.diff(None)

At this point I can see the submodule-change. If I check sourcetree, I can see the changed submodule in the 'unstaged files'. The thing is, I have no clue how to stage the change so I can commit it.

What I have tried:

  • If I commit using repos.index.commit(''), it creates an empty commit.
  • If I try to add the path of the submodule using repos.index.add([submodule.path]), all files in the submodule are added to the repository, which is definately not what I want.
  • If I try to add the submodule itself (which should be possible according to the docs) using repos.index.add([submodule]), nothing seems to happen.
Psalmody answered 5/8, 2015 at 14:46 Comment(1)
Same problem here. API reference gitpython.readthedocs.org/en/latest/… mentions repos.index.add([submodule]) but… yeah, nothing happens. A bug maybe? I reported it here: github.com/gitpython-developers/GitPython/issues/335Lupercalia
T
6

There are two ways to add new submodule commits to the parent repository. One will use the git command directly, the other one will be implemented in pure-python.

All examples are based on the code presented in the question.

Simple

repos.git.add(submodule.path)
repos.index.commit("updated submodule to 'wanted commit'")

The code above will invoke the git command, which is similar to doing a git add <submodule.path> in a shell.

Pythonic

submodule.binsha = submodule.module().head.commit.binsha
repos.index.add([submodule])
repos.index.commit("updated submodule to 'wanted commit'")

The IndexFile.add(...) implementation adds whichever binsha it finds in the submodule object. This one would be the one in the parent repository's current commit, and not the commit that was checked out in the submodule. One can see the Submodule object as a singular snapshot of the submodule, which does not change, nor does not it know about changes to the submodule's repository.

In this case it seems easiest to just overwrite the binsha field of the submodule object to the one that is actually checked out in its repository, so adding it to the index will have the desired effect.

Toolmaker answered 8/8, 2015 at 21:15 Comment(2)
Thanks for this, works like a charm. Somewhat related: do you know how to show the current submodule hash? If I just switch branches and update() or pull(), the hash stays the same. I thought I understood git, but this doesn't seem to click for me :)Psalmody
To answer my own question: repos.submodule_update(force_reset=True) will reset the submodule to where it should be according to the current branch. submodule.module().head.commit will then contain the sha of that commit in the submodulePsalmody

© 2022 - 2024 — McMap. All rights reserved.