Exclude Subproject commit Git
Asked Answered
P

3

5

How can I exclude Subproject commit .... I changed nothing in the submodule, only pull changes from remote repository! I think I commited something unneeded in the main repository, when created submodule. Any ideas?

1) When I created submodule git diff in main repository also showed

submodule-path:
    Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e

and I commited this

2) then someone commited to submodule, so it has the following log

2ff89a2bfcaa0 last commit
5a8162ff9a602d  first commit

3) I updated submodule with

git submodule update --remote --merge

4) now git status shows

modified:   submodule-path (new commits)

But I changed nothing in the submodule, only pull last remote changes! And I need this last changes

git diff shows

diff --git a/submodule-path b/submodule-path
index 5a8162f..2ff89a2 160000
--- a/submodule-path
+++ b/submodule-path
@@ -1 +1 @@
-Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e
+Subproject commit 2ff89a2bfcaa014885a70b0da86e997ecd8d0688
Poynter answered 30/9, 2019 at 15:3 Comment(3)
"Pull" means "run fetch, then run merge". Merge may well (and in this case did) change something. You almost certainly want to change something, too. What you need to know is what changes you want to make, and where and how to make them. We (StackOverflow) can tell you how to manipulate submodules in various ways, but we cannot tell you what changes you want to make.Embryologist
below @oktapodia suggests git submodule update -f --init, but it resets to first commit, but I need the last.Poynter
The default update subcommand just forces the submodule back to the commit recorded in the superproject. But there isn't necessarily a single "last" commit in any Git repository. I'll write something up, but remember, submodules are inherently complicated.Embryologist
N
3

Update:

This is NOT an error. The submodules just work in this way.

The main repo doesn't track the submodule's files. It only tracks the submodule's url and commit id (the submodule's state at a specific point).

Quote from Starting with Submodules in book Pro Git

Although sbmodule DbConnector is a subdirectory in your working directory, Git sees it as a submodule and doesn’t track its contents when you’re not in that directory. Instead, Git sees it as a particular commit from that repository.

Since you updated the module with git submodule update, you have to stage the change (in fact, the updated commit id). If you don't wanna update the tracking of submodules, just don't use git submodule update at the beginning, or just discard the change.


It's very likely that the submodule is HEAD detached. Go in the submodule, reset the submodule to fix the HEAD detached status.

# Do this in the submodule
git reset --hard origin/master

Then update the submodule to the latest commit.

# run in the project's root, not the submodule's
git submodule update --remote --merge
Notify answered 30/9, 2019 at 15:22 Comment(3)
yes, it was detached, but nope, still see modified: submodule-path (new commits) =( What did: 1) go to submodule dir, 2) git checkout master, 3) git reset --hard origin/master4) in projects root git submodule update --remote --mergePoynter
@IvanKush The submodules just work in this way. The main repo doesn't track the submodule's files. It only tracks the submodule's url and commit id (the state at a specific time). Since your updated the module with git submodule update, you have to stage the change (in fact, the updated commit id).Notify
@IvanKush Updated my answer explaining how the submodule works.Notify
E
3

First, let's try to make some things here clear. It's hard because when you work with Git on your own, it's complicated. When you add a second Git repository–to which you git push your own commits, and from which you git fetch other people's new commits—that is complicated too. A submodule is nothing more than a third Git repository, and that third Git repository has a fourth Git repository to which you might perhaps git push your own commits, and from which you might git fetch other people's new commits. So we're leaping right into a situation in which there are at least four Git repositories, all of which are somewhat independent of each other.

We could try to draw pictures but even pictures will be a bit muddy. How do we keep four repositories straight? Git has names for two of them: the two that you work with directly, yourself. One is the superproject, which is where you are running git diff and seeing:

diff --git a/submodule-path b/submodule-path
index 5a8162f..2ff89a2 160000
--- a/submodule-path
+++ b/submodule-path
@@ -1 +1 @@
-Subproject commit 5a8162ff9a602deb96956854346988e1ee45672e
+Subproject commit 2ff89a2bfcaa014885a70b0da86e997ecd8d0688

The other is the submodule itself: if you cd submodule-path and run various Git commands, you'll see that it is an ordinary Git repository. The only thing unusual about it is that it is almost always in "detached HEAD" mode.

Your superproject Git probably has an origin. That's a repository—well, technically, a short name you can use in this Git to refer to another repository—to which you can git push commits you make in the superproject. You will need to make a commit in the superproject and then git push this new commit to origin. What precisely goes into this superproject commit? We'll see in a moment.

Your submodule Git also has an origin. That's a different other Git repository: the fourth Git in this not-very-well-drawn-at-all picture. It's not clear to me whether you want to send commits to that fourth repository. You do presumably want to get a commit from that repository. There are multiple ways to go about this, including using git submodule update --remote, perhaps with additional options. I prefer to just cd submodule-path and start working directly in the submodule Git as this reduces the problem to things you already know how to do: manipulate one local Git repository based on new commits that have appeared in its origin.

Supposing you just want to pick up some new commit(s) in the submodule

If this is the case, you can:

cd submodule-path           # begin working in your submodule
git fetch                   # update origin/*
git checkout origin/master  # get a detached HEAD on the desired commit
                            # (this assumes `origin/master` is the
                            # desired commit; it's impossible for me
                            # to know which commit you desire)

and now the submodule has the desired commit as its detached HEAD. There is nothing to git push from here: all the commits that reside in this repository are commits obtained from this submodule's origin's Git.

(Using git submodule update --remote may do the cd submodue-path and git fetch and git checkout origin/master for you, all without changing your own working directory. The whole operation runs in its own sub-shell so that none of these cd operations affect where you are. That seems to be what your git submodule update --remote --merge did: there was no need to make a new merge commit, so it just switched to the commit identified by some branch name on origin.)

But if you need to make new commits in the submodule ...

In this case, you may want to force the submodule to be on a branch, so that you're working in a more normal work-flow. Then you'd probably want to git checkout master for instance, and then do various commands. Eventually you might end up with a new commit made in your submodule repository, which you will need to git push to the origin repository of the submodule, so that other people will be able to obtain this commit too.

You can leave the submodule on its branch. The submodule's branch is irrelevant to the superproject Git: the superproject Git cares only which commit is checked out in the submodule. (That's why in the earlier case above, we can just switch the detached HEAD around.)

Now that the submodule Git is on the right commit, you must make a new superproject commit

At this point, you can cd back out of the submodule into the superproject. You'll see in git diff output something exactly like you quoted above, and git status will say:

modified:   submodule-path (new commits)

This doesn't necessarily mean there are any new commits in the submodule repository that aren't in the submodule repository's origin. It just means that the submodule repository is on (as its HEAD, detached or not) a commit that is not the commit that the current superproject status says it should be on.

The problem here is that the current superproject commit is, in a way, defective. It was correct, but it isn't any more, just as the current superproject commit would be defective if you had, say, edited the file README.md locally. This means that you need to make, in the superproject, a new, corrected commit. The superproject Git will make the new commit from whatever is in the index of the superproject repository, so you now need to update the index.

If you'd changed a README.md file, the way you'd update the index is:

git add README.md

But what you changed was not a README.md file. It was, instead, the submodule hash ID. So you need to record the new hash ID in the index. The way you do that is:

git add submodule-path

This takes the hash ID from the submodule by running cd submodule-path; git rev-parse HEAD to gets the raw hash ID—the one that showed up in the git diff—and stuff that hash ID into the index. Now git diff—which compares the index to your work-tree—won't show these Subproject commit lines any more, but git diff --cached—which compares the current (superproject) commit to the index—will show them. Now git status will say that these "new commits" are ready to be committed, rather than not-yet-staged-for-commit.

You can git add any other superproject files (if there are any that need to be updated in the index) at this time. Then:

git commit

in the superproject will make a new commit that will record the hash ID you put into the superproject's index when you ran git add on the submodule path.

You're (locally) done with the update, but here's some things to think about

Note that every commit in the superproject records the hash ID in the submodule. Every time you git checkout a different superproject commit, that not only extracts the right superproject files into the (superproject) index and your (superproject) work-tree, it also extracts the recorded submodule hash ID into the (superproject) index. It does not, by default, cd into the submodule and git checkout that particular commit by its hash ID. You can change this with a setting, or add --recursive to git checkout; or you can just run git submodule update, which tells your Git to cd into each submodule, one at a time, and git checkout the hash ID currently recorded in the (superproject) index.

You will, at some point, need to git push the new commit you made in your superproject, to the origin (of the superproject), so that the new commit with its newly recorded hash ID appears in the Git over at the origin of your superproject. You can do this whenever you like—but suppose you did make new commits in your submodule, and you have not yet used git push in the submodule itself to send those new commits to the origin of the submodule. In this case, the new commit you made in the superproject records the hash ID of a commit that only exists in your local submodule repository. If someone runs git fetch to the superproject Git's origin, they'll get this new hash ID from the new commit you sent, but not be able to find that commit in their clone of the submodule. So if you did make new submodule commits, it's usually best to git push them first, then git push the new superproject commits.

(If you did not make any new submodule commits, there's no problem here.)

Embryologist answered 30/9, 2019 at 15:56 Comment(0)
D
1

Running the command git submodule update -f --init should resolve your issue, this will reset your submodule to the remote HEAD

Difficult answered 30/9, 2019 at 15:7 Comment(4)
nope. It resets to prev submodule commit 5a8162ff9a60. But the last commit is 2ff89a2bfcaa0. I need the lastPoynter
You have to run this command from the git directory, not from the submodule directoryDifficult
yes, I ran it from base dir. Also this command makes detached submodule branchPoynter
I had the same problem as the original poster and this is the only answer that worked for me !!Convertiplane

© 2022 - 2024 — McMap. All rights reserved.