68

I want to add an external directory to an existing repository.

External Dir: /home/some/directory

Working Dir: /htdocs/.git

If I attempt the following command from the /htdocs dir:

git add /home/some/directory

I get an error: fatal: '/home/some/directory' is outside repository

10 Answers10

65

If I need to do something like that I would normally move that external file or directory into my git repo and symlink it's original location to the new one.

mv /home/some/directory /htdocs/directory
ln -s /htdocs/directory /home/some/
git add ./directory

I use this technique when I am developing a plug-in for an application that I want to keep under version control but have to store in a specific location.

csexton
  • 24,061
  • 15
  • 54
  • 57
  • 1
    This does not work at all for me in Mac OS X 10.10.3. Basically Wordpress does not recognize the symlinked plugin directory or files and they do not appear in the WP plugins list. Am I missing something? – Adam Christianson May 05 '15 at 02:13
  • With smb share any idea? I want to sync Firefox bookmarks using git. – Matthis Kohli May 14 '18 at 16:03
  • That's fantastic. I had tried doing a symlink in the other direction and git was throwing a fit. ;) – zx81 Apr 08 '19 at 11:01
  • What if you want to copy/tar/gzip all things in **/home/some**? In this case, you just end up with getting nothing but links, missing actual contents. – JUNPA Aug 17 '22 at 03:44
  • For clarity: the external files are not in the same file structure as the git repo. So rather than the symlink within the repo, the actual files are moved into the repo directory structure (htdocs). A symlink is created so that the other application or workflow can work on home/some..... – satchel Mar 03 '23 at 18:45
26

I had the same error... Googled it to death... not much came out.

Christian's answer worked :

git --work-tree=/ add /home/some/directory

But then "work-tree" got me going. I grep'd all Git docs and came up with core.worktree.

I used

git config --global core.worktree /

And voila! I can now add from any directory in the system. I don't know if it will cause problems any other places, but I'll try to update as I go along.

budi
  • 6,351
  • 10
  • 55
  • 80
MotherDawg
  • 669
  • 7
  • 7
  • 1
    did you mean to write "I can now add from *any* directory in the system."? Just curious, the copy editor in me wants to edit your answer oh so badly. :P – Will Lanni Feb 20 '14 at 19:06
  • 3
    Yes I did, that's what a mild case of dyslexia does for you... your brain has already finished the paragraph and doing something else while your fingers are still in the middle of it. (Sorry for the late reply) – MotherDawg Nov 13 '14 at 07:20
  • So i cannot do `git add *` :P – Nishant May 19 '15 at 13:03
  • I'm not sure what happened, but after trying this GitHub could no longer find my repository, then crashed. – StarSweeper Apr 27 '17 at 22:27
  • Similar answer https://stackoverflow.com/a/8040817/5459638 has other comments on `git --work-tree=/ add /home/some/directory` – XavierStuvw Jul 01 '20 at 04:48
  • 2
    After caution it could be better not to make experiments with `/` but choose a test directory inside your `/home/user` directory. And also play with your local repo using `--local`, the default by the way, instead of `--global` – XavierStuvw Jul 01 '20 at 05:53
16
git --work-tree=/ add /home/some/directory
Christian Specht
  • 35,843
  • 15
  • 128
  • 182
anon
  • 169
  • 1
  • 2
  • 4
    This explains it a bit: http://stackoverflow.com/questions/5283262/what-is-git-work-tree-why-have-i-never-needed-to-set-this-env-var-why-now although it's not clear to me what someone would get if they cloned that repo – Sam Hasler Apr 23 '14 at 11:21
  • It also makes writing .gitignore very complicated and git status and git add --a will remove files outside the git working directory. You could set the work directory as a local repository setting, but that will by default monitor everything under the set directory. Which would again, require gitignore's help. More trouble than it's worth. – Ray Foss Jun 10 '15 at 16:32
  • See https://stackoverflow.com/a/8626989/5459638 in this discussion board for other comments on this solution – XavierStuvw Jul 01 '20 at 05:22
  • How to eclude /storage/sdcard1/.android_secure on Android ? `git --work-tree=/ add /storage/sdcard1` simply doesn't work on rooted phone. – Khurshid Alam Aug 13 '23 at 10:06
10

There's a really simple solution to this.

Let say you're Git-repo is in /var/data/my-app and you want to add /var/data/public/ to that repo. You can't use 'add' because Git won't add resources outside of the repo's root directory. So..

Solution:

  1. Move the /var/data/public/ directory into your Git-repo root (/var/data/my-app).

  2. Create a sym-link (symbolic link) inside of /var/data/public to the /var/data/my-app/public folder, using: ln -s source_file_or_directory virtual_file_or_directory

Then, just add the moved file or directory to Git using git add in the normal fashion. Your Git source control is now tracking the desired file/folder, and your sym-link in the external directory assures that the file/folder is accessible to whatever else!

Stormbytes
  • 189
  • 4
  • 11
  • 1
    this doesn't actually track anything in the target directory. It just tracks the link. Right? – incandescentman Feb 14 '14 at 07:53
  • @PeterSalazar no, since Stormbytes suggested to move the target dir into the git repo. The symlink maintains the original location. If you added the link in the repo, you would be correct. – shiri Dec 09 '14 at 15:02
  • 1
    This won't work well if there are multiple users using the same machine contributing to the same git project. Example: Suppose there are two Users in the same machine: U and T. U linked symbolically the _/var/linked_ directory to somewhere inside its home folder. Another User T wants to edit some file inside the _/var/linked_ directory, but he has to have permissions for it. Even if T has the write permission to U's linked directory, T will be editing the working copy from U's repository. – gallo Mar 23 '16 at 21:21
  • I had some essential dlls that I wrote that resided in an external folder. I closed the solution in VS, copied the folder to my solution folder, opened the project again, and git registered the added folder as a change. I labeled the change and clicked Commit. Now the files I need are in the repository. – Alan Aug 04 '23 at 06:05
4

If the code that you want to add to your repo is not too big, you could also automatically copy it to your repo each time before you push.

In my case I for example need one R file, which I modify quite often, in several repos and I wrote a little shell script:

#!/usr/bin/env bash

cp -r /some/directory/file.R .
git add .
git commit -m "add"
git push

...and I run this script in order to push all changes, including the ones in /some/directory.

  • I like this solution, it might not be up-to-the-second until the files are copied, but it maintains a git copy, it's clean, simple, and will be predictable to anyone cloning the repo. Even better idea might be to include the "sync" script in the repo itself, maybe with a "restore" script to go with it. – Kareem Oct 13 '22 at 12:01
1

This got me thinking, since I would like very much the solution of using a symlinked file/dir but am stuck on a windows computer. As far as I know the symlinks in windows doesnt really work in the same way. So another solution could be to write two scripts/bash functions to "import" and "export" the file(s) in question, such as:

import() {
    cp -fr /home/some/directory /htdocs/
}

export() {
    cp -fr /htdocs/directory /home/some/
}

Then you would have a copy of the file in your repository, which you could git add.

Tubbles
  • 59
  • 4
1

I would make hard links to each of the files in the external directories. As hard link does not make additional overhead over the original file, it could be a perfect sync. The only problem is that a directory cannot be linked (only by super-user), so it must be created to store files.

For example, normally zeppelin support version controls only for notebook files, but I added hard links of the conf files in the parent directory as follows:

.
├── 2A94M5J1Z
│   └── note.json
├── 2G2U2ZR1T
│   └── note.json
├── conf
│   ├── shiro.ini
│   ├── zeppelin-env.sh
│   └── zeppelin-site.xml
└── README.md
JUNPA
  • 220
  • 2
  • 6
0

Or you can use submodule if you want to work across different git repos (ln doesn't work in this way). Try 'man git-submodule'.

superarts.org
  • 7,009
  • 1
  • 58
  • 44
  • I just glanced at this, but having a submodule outside its parent repo looks uglier than just having 2 repos especially for someone pulling from a repo with an external submodule. Have you (or anyone) actually used this? – mikeLundquist Aug 04 '18 at 21:26
-1

use this code to move the directory if you use windows git bash terminal and make a symlink to source

git mv <source_directory> <destination_directory>
git ln -s <source_directory>
-3

Add a symbolic link to the directory within the repository. Then, add the same.

ln -s /home/some/directory/
git add directory
Alan Haggai Alavi
  • 72,802
  • 19
  • 102
  • 127