Hoping someone might know the explanation for this inconsistent behavior. I have had this problem both with public repos as well as my own project repos, but for example’s sake I’ll use the Facebook SDK from GitHub.
If I clone this repo, it checks out into a folder called php-sdk. This is pretty much to be expected, although the repo file listing at GitHub doesn’t show this folder.
If I clone it out as a submodule in another project (which would be a pretty common operation for an SDK like this) I just get the contents of the folder directly outputted into the directory I choose.
I have also had it happen that when I wrap all my project files in a directory and commit it into the repo, it sometimes doesn’t come out in this structure when cloned (same output as the submodule example above.) Changing the name prefix of the .git dir seems to change this, but does not have any effect on the outcome of the submodule command.
Is there a reason these commands all behave differently handling the first directory in the repo structure? Am I misunderstanding how to store my files inside a repo? I guess you could file this under minor nuisance, but I would love to get the conventions for this to make my repos more friendly for cloning.
Basically there is no ‘wrapping’ directory stored as part of the repository. Your expectations that there is one is what is misleading you. A Git repo is just, by default, the directory called
.git. Your sandbox, or the stuff that is checked out, is placed at the same root level that the.gitfolder is located. When you make a clone it automatically checks out the master branch. The .git folder and the checkout is the actual root of your git workspace.By convention, Git will normally infer a name and create a directory for your workspace when you use the clone and
git submodule addcommand. It will create the directory and then it places the git repo (that.gitfolder) and then checkout the master branch files into it. However, you could specifygit clone <repo> .orgit clone <repo> <target_dir>and Git will place the root of your repo and checkout anywhere you want.So if you created a repo like this:
When you clone it later with
git clone repo.gitit is only by convention it is put into a subdirectory calledrepothat has a file calledfooand a directory.git. However, repo is the root checkout directory, not the current directory (you can tell because it will have a.gitdirectory in it). The directory you ran clone from will NOT be the directory that stores the.gitor checkout directory. If you wanted that you would dogit clone <repo> .and then you would see just the file calledfooand a directory called.gitand no directory called repo.If you want there always to be a directory called repo nesting all the source in then you would of created the repo like this:
Then when you clone it by just using
git clone <uri>/repo.gityou’ll have a directory calledrepothat contains a directory.gitand a directory calledrepothat has the foo file. In my opinion this is a layer of indirection that can be cumbersome (I know, I did it…once).Submodule’s are an entry in the main repo as simply a directory which contains another git repo at a certain checkout. When you init and update the submodule the first time it is basically just creating the directory reserved for the submodule by the main repo and then fetches that whole git repo and checkout into that directory. Since you should understand now that a git repo is just normally the .git directory and a checkout along side it it should be obvious why that directory would not also have a different wrapping directory in it. You basically named what directory the submodule should wrap in when you use the
git submodule add <repo> [<target_dir>]command.