0

I want to add an external directory to an existing repository. When I try in /Desktop/.git the following command: git add /home/some/directory

The following error message shows up: Fatal: '/home/some/directory' is outside repository

Is there any solution to this issue? Thanks!

falcon356
  • 57
  • 6
  • 1
    Does [this](https://stackoverflow.com/questions/2383754/git-how-do-you-add-an-external-directory-to-the-repository) answer your question? – mnestorov Apr 10 '21 at 07:14
  • 2
    Does this answer your question? [git: How do you add an external directory to the repository?](https://stackoverflow.com/questions/2383754/git-how-do-you-add-an-external-directory-to-the-repository) –  Apr 10 '21 at 07:15
  • It does but somehow I'm not able to commit the add.. why? – falcon356 Apr 10 '21 at 07:26
  • [Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) might be what you're after. – dlever Apr 10 '21 at 11:58

1 Answers1

2

This sort of thing is outside the design of Git. I don't really want to close this as a duplicate of git: How do you add an external directory to the repository? for several reasons:

  • the person who asked that never accepted any of the answers;
  • the person who owns that question isn't on StackOverflow any more; and
  • none of the existing answers there really addresses all the issues.

When I mention the "design of Git" here, what I really mean is this: a Git repository is a collection of commits, where each commit is a full snapshot of some set of files. That set-of-files all must live (and coexist) within what Git calls a working tree or work-tree.

Besides the working tree, there is also a "git dir". This is where Git's own files—which store the repository contents—are located. By default, the Git directory is in .git in the top level of the working tree.

Hence, if the location of the working tree, in your particular repository, is /Desktop, the Git directory is /Desktop/.git, and vice versa. Since your Git directory is the latter, your working tree is the former. That means every file stored in each commit is always relative to /Desktop: a file named /dir/sub/file.ext—or dir/sub/file.ext; these are interchangeable in Git, and note that there are no folders or directories involved, just forward slashes—is stored in your working tree as the file named file.ext in the folder named sub in the folder named dir in /Desktop.

In other words, Git takes the file's path—complete with embedded forward slashes—and breaks it up into components, such as dir, sub, and file.ext. It then will make the folder dir/sub if needed, making the folder dir if needed. All of this happens in your chosen worktree path. Finally, once necessary folders exist, Git will create file.ext in the right folder, in your chosen worktree path.

This is all based on what's in the commits. The commits themselves are stored in a special, read-only, Git-only, format. Each file within a commit is stored in a Git-only format—not your computer's format, which uses files within folders—in which each file is further compressed and, to save space, de-duplicated across every commit. That means that if some large file is in 10,000 commits, but is the same in all ten thousand commits, there's really only one copy of that file in the repository, in Git's own internal compressed and de-duplicated format. The file's data is stored under a blob hash ID name, which your computer doesn't understand. The file's name is stored as more data, also compressed and de-duplicated!

The file itself is later de-compressed and turned into an ordinary file, and given a name that your computer OS understands, and put into your working tree; only then can you actually work with your file. That's one file from one commit, and it will reside in your working tree, coexisting with every other file from that same commit, also residing in your working tree.1


1Git has the ability to perform what Git calls a sparse checkout, where not every file is copied into your working tree, but this gets rather complicated.


The core.worktree trick in the other question

Git has the ability to separate the Git directory and the working tree. There are multiple ways to do this:

  • git --git-dir=path-to-.git --work-tree=path-to-working-tree command args ...
  • GIT_DIR=path-to.git GIT_WORK_TREE=path-to-working-tree command args ...
  • git config core.worktree path-to-working-tree

and so on.

If and when you use these various options, you have to be careful of, and aware of, various caveats. For instance:

  • The --git-dir and --work-tree arguments set the environment variables. (This avoids the stumbling block in the next bullet item.)
  • The environment variable setting depends on your shell: not every shell uses this particular syntax. Note that any env-var setting here may be overridden by a sub-process; the --git-dir and --work-tree arguments do this, for instance.
  • If you do separate the Git directory and work-tree, make sure the Git directory is not inside the chosen working tree. If it is, it may be seen as a submodule.
  • Commands, including hooks, that run within these may accidentally import or fail to import these environment variables at times they should not (e.g., working inside a different work-tree) or should (e.g., during execution of a hook). This may cause those commands to misfire. You'll need to be able to diagnose these situations and make corrections as necessary.

Overall, this can be made to work: you just need to be prepared for surprises. Because of the potential for surprises, I'd recommend always avoiding setting either the Git directory or the working tree to any location you cannot easily restore from some alternate copy or backup copy.

torek
  • 448,244
  • 59
  • 642
  • 775