Daniel
Daniel

Reputation: 15453

I want to push all my files in a way that I can open them all on repository afterwards

I have no idea what happened that Git started telling me that I added another git repository inside my current repository. I don't remember doing that, I have been working on writing code and configuration files all day.

So it gave me this warning: adding embedded git repository: client

I tried doing git rm --cached client -f, Git didn't care, warning still there.

so I did a git add .

When I pushed the project, I could not open up the client/ folder as a link on the Github repository.

I deleted the Github repository.

I am back to changes not staged for commit: modified: client (modified content, untracked content), it does not let me do git checkout -- client/ either.

I essentially want to ensure that when I create a repo for this project and push all these folder that I am able to click on the folders and view the files inside of them.

This is my Dockerfile.dev inside of client/:

FROM node:alpine
WORKDIR '/app'
COPY ./package.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "start"]

This is my Dockerfile for production purposes inside of client/:

FROM node:alpine
WORKDIR '/app'
COPY ./package.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx
EXPOSE 3000
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html

I don't believe any of the configuration above could have create a .git folder inside of client/.

I looked through my command line history and I do not see where I ran a git init on the client/ directory.

At this point how do I clean this up? git rm --cached client did not seem to work and neither did git clean -f -d.

Upvotes: 1

Views: 487

Answers (1)

torek
torek

Reputation: 489508

I am back to

changes not staged for commit:
    modified: client (modified content, untracked content)

This indicates that your existing Git repository is treating the path-name client as a submodule. A submodule is nothing more or less than a particular form of reference to some other Git repository.

This whole picture can get confusing very quickly, since every local (e.g., on-your-laptop) Git repository usually contains a reference to another Git repository already: the one that's on your hosting provider, such as GitHub. That is, if we draw a relationship, we get something like this:

+-----------------+                +-----------------+
|  your Git repo  |   --origin->   |   GitHub repo   |
|=================|                |=================|
|    commits      |                |     commits     |
|  (shared w/     |   <=========>  |                 |
|   origin)       |                |                 |
|-----------------|                |                 |
|   branch names  | (private)      |                 |
|-----------------|                |-----------------|
| remote-tracking |                |  branch names   |
| names: origin/* | <------------- |                 |
+-----------------+                +-----------------+

There are two repositories, one on your laptop (your Git repo) and one on GitHub or Bitbucket or GitLab or whatever. Yours calls theirs origin. You and they share commits by copying back and forth: you run git fetch to get new commits from them, and you run git push to send new commits to them. They have branch names like master and develop and so on, and you have branch names, but you also have remote-tracking names like origin/master. Your Git simply copies their branch names to your repo, while adding origin/—the name you are using to hold the URL for the GitHub repo—in front.

Each of the commits in these two repositories, like any commit, has a unique hash ID. If you and they have the same hash ID for some commit, you have the same commit. So when your Git talks with their Git, it can just ask: do you have hash ID a123456...? or tell it: here's commit a123456... and provide the full contents of that commit.

Submodules

So far so good, but now you've thrown a submodule into the mix.

In a submodule, each of your commits holds the raw hash ID of a commit in some other Git repository. This "other Git repository" is a third Git repo:

          +-----------------+
          |  your Git repo  |
          |=================|
a123456 > |    commits      |
   |      |-----------------|
   |      |   branch names  |
   |      |-----------------|
   |      | remote-tracking |
   |      | names: origin/* |
   |      +-----------------+
   |
   |          +--------------+              +--------------+
   +--------> | README.md    |              | README.md    |
              | file1        |              | file3        |
              | dir1/file2   |              | file4        |
              | client ------|---> b789abc: | ...          |
              +--------------+              +--------------+

where b789abc... is actually a commit in this third repo. This third repo of course can also have its own origin, which would be a fourth repository in the picture. That fourth repository is also presumably on GitHub or Bitbucket or GitLab or whatever.

To work with a submodule properly, your own repository—the one Git calls a superproject, which is the one on the left in this second diagram—must contain a file named .gitmodules. This file lists the URL of the fourth Git repository, i.e., the one we didn't draw here.

In this case, we've shown a commit in your repository that contains snapshots of files, plus a gitlink. This gitlink says that for the name client, whoever is working with this repository should clone the submodule repository and tell that Git to git checkout b789abc... (by its unique hash ID).

The URL you are to store in .gitmodules enables anyone who clones your GitHub repository to also clone this fourth repository. After that, their local (laptop) clone can use the hash ID—in this case b789abc...—stored in the gitlink entries of the commits that are shared in your laptop and GitHub superproject repositories, to git checkout the right hash ID in their local Git repository that they make by cloning this fourth Git repository.

(You might need to read over this section many times. It's complicated!)

What if you don't want a submodule?

If you don't want a submodule at all:

  1. Move the other Git repository completely out of the way:

    mv client /some/other/path
    

    (or whatever you use to move everything, including the .git folder).

  2. Copy all the files, but not the .git directory/folder, from the place you moved all this stuff to.

(Another way to do this that might be easier: move the .git directory out of the client/ subdirectory, or remove it entirely.)

Now you have ordinary files—which you did before—but ordinary files that you can git add in the ordinary way because there's no .git folder in the client/ folder standing in the way. Your Git repository won't try to control some other Git repository via all this submodule stuff.

Unfortunately, you must do this after getting rid of any submodule that you already created. This is painful. Be very sure you want to do this. If you have existing commits that list client as a submodule, you'll have to either be very careful whenever you use those existing commits, or do a major history rewrite operation to replace all those commits with new-and-improved ones that don't use client as a submodule.

See the last section below if you haven't made any commits that refer to this submodule and don't have a .gitmodules file.

What if you do want a submodule, but just want to update it?

This gets a little bit tricky, but it's really not that bad. Remember: the submodule is a Git repository. It should have a counterpart over on GitHub or whatever, which the submodule calls origin. The submodule itself has little or no idea that it's living underneath a superproject: it's just a regular old Git repository. The only thing special is that the superproject tends to cd into the submodule Git and tell it to git checkout one commit by hash ID, putting it into detached HEAD mode.

So: enter the submodule yourself, and take it out of "detached HEAD" mode, by either creating a new branch name for the current commit, or checking out some existing branch name. If you have changes that you need to save, you can git stash them or make a commit here first, then return to this commit later. If your changes are really simple—say, updating the README file slightly—you can just re-create them.

Now, re-create your changes on this branch, or commit them on this branch whose name you just invented, or whatever it takes to commit them on some branch:

... do work ...
git add <files>
git commit

(and supply commit message, etc). You'll see that this makes a new commit, which gets its own new unique big ugly hash ID. You can now git push or use a pull request to send this new commit, under its new or existing branch name, to the fourth Git repository, the one this submodule Git calls origin.

(If you have to go through a pull request, this can take a long time, obviously. If you like to live dangerously, you can go ahead and use the new hash ID on the assumption that whoever controls the pull requests will take your commit as is. If not, wait until they take it, or notify users that they might not be able to use the superproject update you're about to make. Remember, your superproject records raw hash IDs. If the people controlling the PRs take your changes slightly differently, the commit they put into the upstream repo will have a different hash ID, and you'll have to update your submodule again.)

Now your new commit in the submodule is available to everyone else too. You're now done updating the submodule, and can go back to the superproject:

cd ..     # or whatever to get to the superproject

Running git status in the superproject will now show that the submodule has a new commit in it. (Running git diff or git submodule status will show similar things, although you can configure git diff to show actual diffs instead of just a raw hash ID. You can configure git status in complicated ways here too, but the default is to just say (new commits).)

Your job is now to record the new hash ID in the gitlink that will be committed in your next commit:

git add client

Now the changes are staged—git status will show them under changes staged for commit this time. Now you can git commit the result as an updated gitlink, along with everything else that goes into each new commit you make. You now have an ordinary commit—just, one that uses a gitlink to refer to a commit in a third Git repo that refers to a fourth Git repo, that your superproject calls a submodule.

What if you don't want a submodule, don't have a .gitmodules, etc, and have not made any commits with this weird submodule stuff yet?

(Note: It sounds like you have already made some commits, because you talked about looking at the commits via the GitHub web browser. So this may not apply at all.)

If you have run:

git add client

and client has its own .git, a modern Git will notice and create the first part—but only the first part—of a submodule: a sort of half-baked one. This one is missing the .gitmodules file that tells future git clone operations where the fourth Git repository is, so that those folks' Gits can make their own third repositories.

If you haven't committed this yet, though, this gitlink isn't in any commits. That makes cleaning it up easy. Just run:

git rm --cached client

to remove the gitlink entry from your index/staging-area. Then, once you have de-.git-ified the client directory (i.e., now if you already did this, in a moment if you haven't yet), you can git add client and it will add the files in the client folder (and recursively, any files in any sub-folders) this time.

Upvotes: 1

Related Questions