Force Git submodules to always stay current
Asked Answered
D

4

99

I love git submodules. Also, I hate git submodules. What I love about them is how it enables to you to cleanly compartmentalize dependencies etc. I get the point of having them point to a specific commit on a repo, I do. But in my case, I'm building a library that will be used in another project, so I want to keep it in that seperate repo.

However, the annoyance comes when I'm working on a daily basis on this library and I constantly have to switch back to the app using my library to commit the pointer update.

So, is it possible to have a git submodule just always be on the head of the repo it's pointing at while I'm constantly updating and adding to this library?

Deka answered 4/5, 2012 at 6:15 Comment(1)
Does this help? #1778354Puncheon
T
38

UPDATE: As of git 1.8.2, there seems to be a solution. Please see VonC's answer down below. The original answer is left here for the users of git < 1.8.2.


No, and this is by design. If there were a way to point a submodule to the "current head" of some other repository, then it would be impossible to retrieve a historical version (such as a tagged version) from the main repository. It wouldn't know which version of the submodule to check out.

Having said that, you may be interested in the git subtree script. This offers a different way of working with submodules that may be more compatible with your workflow. I was just reminded of this by the recent post on HN.

Tubulure answered 4/5, 2012 at 6:16 Comment(5)
yes, i get that, what I'm saying is that I want my parent repo to just automatically update the submodule pointer whenever there are changes committed locally in the submodule. If I have project A that has submodule X, when I go into submodule X while working on project A, I'm constantly having to do 2 commits, one in the submodule, then again in the parent. Not a huge deal if you're working on a submodule that doesn't change much, but when you're constantly having to go back and forth, it gets to be really annoying.... Seems like i should just be able to have my local repo just commit bothDeka
translation: tell my local repo to just automatically commit the submodule pointer update for me when i commit changes to the submodule ...Deka
I suppose you could write a script that you use when committing to the submodule, that would automatically make a corresponding commit in the parent module. Or, you could write a script that you run in the parent module working directory, that automatically makes commits for any submodules that have been updated since the last parent project commit.Tubulure
@Ben: I've updated my answer with more information that may be helpful.Tubulure
This is no longer true as of Git 1.8.2 (Mar 2013). github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt . Git added the feature for submodules to point to tip of a remote branch.Socinian
C
92

As I mention in "git submodule tracking latest", you can since git 1.8.2 (March 2013) make a submodule track the HEAD of branch:

git submodule add -b <branch> <repository> [<path>]

A submodule SHA1 is still recorded in the parent repo as a gitlink (special entry in the index)

But a git submodule update --remote will update that entry to the SHA1 matching the HEAD of a branch of the submodule remote repo.

If you have an existing submodule, you can make it follow a branch with:

cd /path/to/your/parent/repo
git config -f .gitmodules submodule.<path>.branch <branch>

cd path/to/your/submodule
git checkout -b <branch> --track origin/<branch>
  # if the master branch already exist:
  git branch -u origin/<branch> <branch>

cd /path/to/your/parent/repo
git add path/to/your/submodule
git commit -m "Make submodule tracking <branch>"
Couturier answered 6/8, 2015 at 9:23 Comment(9)
Every time that I run git submodule update --remote the submodule back to the commit and lost the HEAD referenceOverabound
Doing git submodule foreach git pull it doesn't happen.Overabound
@MarceloFilho that is not surprising considering a submodule does not checkout a branch. If it is configured to follow a remote branch, then git submodule update --remote --recursive is the only command necessary. Check your .gitmodules to see if that/those submodule(s) follow(s) a branch.Couturier
Yes my .gitmodules is pointing the submodule to a branch (master) but to a local one: master = master.Overabound
@marc and the update remote does not work? What is the git version you are using?Couturier
The git submodule update ... works fine. The point is that every time after this update the branch of the submodule back to point to a commit hash (current master HEAD) and not to the master HEAD itself for example.Overabound
@mar exactly, that is how a submodule is supposed to work. It checkout it's gitlink, never a branch.Couturier
@Couturier are there any plans or discussion around letting the gitlink point always to HEAD of the branch rather than a SHA1, or alternatively an option, ideally in the .gitmodules so that git status doesn't fret about (new commits)? it's nice that update --remote updates it but would be even nicer if we had the option not to need commits in main branch updating the submodule gitlinks.Brietta
@PartlyCloudy Not that I know of. "git status doesn't fret about (new commits)" should mean --ignore-submodules (https://mcmap.net/q/14042/-git-can-i-suppress-listing-of-39-modified-content-39-dirty-submodule-entries-in-status-diff-etc)Couturier
T
38

UPDATE: As of git 1.8.2, there seems to be a solution. Please see VonC's answer down below. The original answer is left here for the users of git < 1.8.2.


No, and this is by design. If there were a way to point a submodule to the "current head" of some other repository, then it would be impossible to retrieve a historical version (such as a tagged version) from the main repository. It wouldn't know which version of the submodule to check out.

Having said that, you may be interested in the git subtree script. This offers a different way of working with submodules that may be more compatible with your workflow. I was just reminded of this by the recent post on HN.

Tubulure answered 4/5, 2012 at 6:16 Comment(5)
yes, i get that, what I'm saying is that I want my parent repo to just automatically update the submodule pointer whenever there are changes committed locally in the submodule. If I have project A that has submodule X, when I go into submodule X while working on project A, I'm constantly having to do 2 commits, one in the submodule, then again in the parent. Not a huge deal if you're working on a submodule that doesn't change much, but when you're constantly having to go back and forth, it gets to be really annoying.... Seems like i should just be able to have my local repo just commit bothDeka
translation: tell my local repo to just automatically commit the submodule pointer update for me when i commit changes to the submodule ...Deka
I suppose you could write a script that you use when committing to the submodule, that would automatically make a corresponding commit in the parent module. Or, you could write a script that you run in the parent module working directory, that automatically makes commits for any submodules that have been updated since the last parent project commit.Tubulure
@Ben: I've updated my answer with more information that may be helpful.Tubulure
This is no longer true as of Git 1.8.2 (Mar 2013). github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt . Git added the feature for submodules to point to tip of a remote branch.Socinian
I
0

Why don't you make changes inside the submodule directory, which itself is a git repo? This way, your app will always have updated library.

Caveats:

  1. You still need to commit the submodule change inside your app repo to put the change in version control (for the app).

  2. If there are more apps than one that are using this library, than this is not going to work, since only one app will be up-to-date at any given time.

Insolent answered 4/5, 2012 at 6:34 Comment(1)
"Why don't you make changes inside the submodule directory" because it's detached and origin it may be already way ahead so you would introduce a conflict, this people would like always get HEAD version of submodule rather to stick to specific commitFustigate
A
0

There is no such thing for the moment. To keep the code up-to-date, I use the following commands:

download all for the first time: git clone --recursive http://github.com/<your repo>
download updates in existing repo: git submodule update --remote --recursive --merge

Abilene answered 6/11, 2020 at 9:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.