Reputation: 6673
I recently added a new site to my laravel as an e-commerce. When I try to push this site to my production server I get an error about it not being tracked.
When I run git status I get this:
C:\Users\Kye\sites\laravel>git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
(commit or discard the untracked or modified content in submodules)
modified: e-commerce/demo (modified content, untracked content)
no changes added to commit (use "git add" and/or "git commit -a")
When I try to add the folder, and files:
git add e-commerce/demo -A
It still doesn't work and says its untracked. How can I commit this change and add the files?
C:\Users\Kye\sites\laravel>git add .
C:\Users\Kye\sites\laravel>git add -A
C:\Users\Kye\sites\laravel>git commit -m "test"
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
modified: e-commerce/demo (modified content)
no changes added to commit
C:\Users\Kye\sites\laravel>git push
[email protected]'s password:
Everything up-to-date
C:\Users\Kye\sites\laravel>
Upvotes: 1
Views: 1145
Reputation: 487775
This:
Changes not staged for commit: modified: e-commerce/demo (modified content)
means that you already have a submodule. Specifically, the (modified content)
is the giveaway.
When a superproject uses a submodule—as in this case—the superproject itself is a Git repository, and the submodule is another, mostly-independent Git repository. The superproject has a few crucial control files:
.gitmodules
contains information the superproject Git needs so as to run git clone
to get the submodule repository to exist. This stuff is only needed once!
.git/config
contains information the superproject Git has squirreled away after running git clone
so that the submodule now exists.
This second file also, of course, contains all the information the superproject repository needs to do git fetch
and git push
to the Git repository from which you cloned the superproject.
Note that because the submodule is a Git repository, it has its own .git
, containing its own .git/config
. This tells the submodule how to git fetch
and git push
to the Git repository from which the submodule Git was cloned (by the superproject Git). At this point, there are four interesting repositories:
git status
.origin
.(cd path; git status)
(more or less) and found that there was something modified.origin
, from which your submodule was cloned.In general, here is how you deal with changes you make in the submodule:
Commit them in the submodule Git, somewhere—preferably to a branch. This part is pretty easy, once you're very familiar with Git.
Send them to whoever controls the upstream of this submodule. This may involve creating a fork of some project on GitHub, for instance. This part is a little harder, but is just the same as you do on any repository where there is an upstream, so once you're very familiar with Git, it's not hard.
Convince the owners of the upstream of the submodule to accept your changes. If you own this upstream yourself, that's pretty easy: just convince yourself to take your own changes. If someone else owns it, you may have to do a lot of convincing, and you might end up committing something different, after however much back-end-forth it takes. This part is often very hard! It depends on the upstream.
(Or, of course, you can just use your fork in the future, i.e., change the URL you store in the .gitmodules
and .git/config
of the superproject. After you do that, you own the upstream, and you just have to convince yourself, which as we just saw, is probably a lot easier.)
Now that these changes are committed in the upstream repository, you can rely on them in future clones, so that's all good. Use git checkout
in your submodule to get the right commit checked out. Use git fetch
there if you need to, to pick up the correct commit from the upstream. Make sure that git rev-parse HEAD
prints out the right commit hash ID at this point, because that's what we're about to use. Remember that Git is all about commits and their hash IDs. Branch names are only important in terms of letting us find hash IDs.
Finally, now you can run git add e-commerce/demo
in your superproject. When you make your next commit in the superproject, your Git will record the hash ID of the commit to check out from the submodule.
The reason we did all this stuff in steps 1-4 is not to make your current repositories work. (We could do that much more simply.) It's to make future clones of the superproject work.
In the future, someone will run:
git clone <url for superproject>
This will get them a clone that has a .gitmodules
file. In that .gitmodules
file, they will have another URL, that specifies how to clone the submodule.
Next, they will run git checkout
if necessary (if they want a particular commit or branch or whatever), and then git submodule update --init
to make their Git clone the submodule, as directed by the .gitmodules
file. That will use the URL stored in .gitmodules
, and will copy information into their .git/config
for their superproject clone. The last step of this git submodule update
is that their Git will look at the current commit to see what hash ID to git checkout
in the submodule. Their superproject Git will, at this point, do the equivalent of (cd submodule; git checkout hash)
, putting their submodule onto the commit that you managed to save in your step 3. You recorded that hash ID in your superproject Git at step 5; you got that hash ID ready in your step 4; but you got that hash ID into the upstream repository in step 3.
You already had a commit you could use, but when future-person future-clones the superproject, they don't have your submodule yet. They get a copy of .gitmodules
, which gives them a URL for another git clone
. They run another git clone
and get a submodule repository. The submodule they get comes from their upstream, as directed by the .gitmodules
file; that clone needs to have the commit whose hash ID you record in your step 5, when you make your superproject commit.
That's what makes this hard. It's why some people refer to these as sob-modules. :-) It really does all work, it's just complicated. It's not that bad if you control the submodule's upstream.
Upvotes: 3