threads / bug / 57956

git bug: Including a git repository in a directory

Subject: git bug: Including a git repository in a directory

## tl;dr

3 messages between Jun 6, 2022 and Jun 6, 2022.

replies: 2people: 3as markdown or json

Steven Jonn Edlefsen· Jun 6, 2022, 05:43 UTC · lore

Git cannot commit/push a directory with a git repository in a sub-directory.

The sub-directory with the git repository and the directories below are set to the “master” branch, while the directories above remain set to the new branch.

When the top directory is committed, the sub-directory with the git repository appears as an empty file.

Even when the subdirectory branch name is changed from master to the new branch and the top directory is re-commited/pushed, the same problem occurs.

When the git repository in the sub-directory is removed, e.g. the .git file is removed, and top directory is committed/pushed, the subdirectory has all the sub-directories and files.

Steve Edlefsen
René Scharfe· Jun 6, 2022, 11:00 UTC · re: Steven Jonn Edlefsen · lore

Re: git bug: Including a git repository in a directory

Am 06.06.22 um 07:43 schrieb Steven Jonn Edlefsen:
Show 17 quoted lines
> Git cannot commit/push a directory with a git repository in
> a sub-directory.
>
> The sub-directory with the git repository and the directories below
> are set to the “master” branch, while the directories above remain
> set to the new branch.
>
> When the top directory is committed, the sub-directory with the
> git repository appears as an empty file.
>
> Even when the subdirectory branch name is changed from master
> to the new branch and the top directory is re-commited/pushed,
> the same problem occurs.
>
> When the git repository in the sub-directory is removed, e.g.
> the .git file is removed, and top directory is committed/pushed,
> the subdirectory has all the sub-directories and files.

This is intended behavior. A repository inside another one needs special handling. Git provides the submodule feature for that. A simpler alternative for some use cases is called subtree.

That's all I can tell you, as I haven't used submodules and subtrees myself. At least I hope these keywords help you explore your options. Others will probably chime in with advise on which one to use if you explain _why_ you want to combine multiple repositories.

René
Glen Choo· Jun 6, 2022, 16:57 UTC · re: René Scharfe · lore

Re: git bug: Including a git repository in a directory

Hi!
René Scharfe <l.s.r@web.de> writes:
Show 22 quoted lines
> Am 06.06.22 um 07:43 schrieb Steven Jonn Edlefsen:
>> Git cannot commit/push a directory with a git repository in
>> a sub-directory.
>>
>> The sub-directory with the git repository and the directories below
>> are set to the “master” branch, while the directories above remain
>> set to the new branch.
>>
>> When the top directory is committed, the sub-directory with the
>> git repository appears as an empty file.
>>
>> Even when the subdirectory branch name is changed from master
>> to the new branch and the top directory is re-commited/pushed,
>> the same problem occurs.
>>
>> When the git repository in the sub-directory is removed, e.g.
>> the .git file is removed, and top directory is committed/pushed,
>> the subdirectory has all the sub-directories and files.
>
> This is intended behavior.  A repository inside another one needs
> special handling.  Git provides the submodule feature for that.  A
> simpler alternative for some use cases is called subtree.

As René described, this is intended behavior - repositories cannot contain entire repositories with `.git` inside them [1]. As far as I know, this is security feature because `.git` can contain sensitive files that you wouldn't want to clone down, e.g. .git/config can make "git" execute arbitrary code.

What happened in your case is that Git noticed that the subdirectory is a repository and automatically 'sanitizes' it for you by converting it into (what is essentially) a submodule [2]. When a subdirectory is a submodule, Git stores a single commit id for the entire subdirectory - you you can no longer change individual files inside the subdirectory.

To demonstrate this "single commit id" behavior, this is what happens if you tried to `git init` a subdirectory in an existing project:

  $ git init foo
  Initialized empty Git repository in /Users/chooglen/Code/repo/foo/.git/
  $ git add foo
  error: 'foo/' does not have a commit checked out

Notice the line above! We can't add `foo` because it has been converted into a (pseudo) submodule [2].

  $ (cd foo && git commit -m "foo" --allow-empty) # create a commit
  [main (root-commit) 9e27581] foo
  $ git add foo
  warning: adding embedded git repository: foo
  hint: You've added another git repository inside your current repository.
  hint: Clones of the outer repository will not contain the contents of
  hint: the embedded repository and will not know how to obtain it.
  hint: If you meant to add a submodule, use:
  hint:
  hint:   git submodule add <url> foo
  hint:
  hint: If you added this path by mistake, you can remove it from the
  hint: index with:
  hint:
  hint:   git rm --cached foo
  hint:
  hint: See "git help submodule" for more information.
  $ git diff HEAD 
  diff --git a/foo b/foo
  new file mode 160000
  index 0000000..9e27581
  --- /dev/null
  +++ b/foo
  @@ -0,0 +1 @@
  +Subproject commit 9e27581b9eb91c0f1699eb18a2e81d758de9209d

Now that there is a commit in the subdirectory repository we can `git add` it, but only as an entire commit. We cannot just add individual files.

If you truly need a repository inside of another repository. You may want to consider submodules/subtrees as René mentioned.

[1] A repository can contain a "bare" repository because a bare repository does not have `.git`, but that isn`t relevant to the discussion here. [2] A submodule technically also has to have an entry in the .gitmodules file.

← back to recent threads