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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

René Scharfe <l.s.r@xxxxxx> writes:

> 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.




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux