I have the following setup:
mkdir /base; cd /base
git init a
touch a/file.txt
git init b
cd b
git config core.worktree=/base
git add ../a/file.txt
I have a /base
folder, which contains two repositories (a
and b
). Repo a
contains just a file (not even commited). Repo b
set the worktree to /base
(where both repos resides). When I try to add the file.txt
from repo a
, it did not work (it just is not staged).
When I remove the .git
folder from a
, I can add the file.
rm -rf ../a/.git
git add -vvv ../a/file.txt
I am not exactly sure why this is the case. Maybe git prevent adding the file because it thinks it is a submodule? I've tried to prevent this with some submodule settings, but with no effect.
git config submodule.ignore all
git config submodule.active false
How can I trick git to forcefully add the file? (-f
is just for ignored files and -v
gives no information).
CodePudding user response:
You can't.
More precisely, the path name of a file in some commit must consist only of "descending" components, all of which reside in this repository, not in any other repository on the file system. So if a file's path name is ../dir/file
, you can't add it, and a if a file's name is dir/sub/file
where dir/sub
contains a .git
, you can't add it.
That last restriction is the submodule restriction:
Maybe git prevent adding the file because it thinks it is a submodule?
It is a submodule, if it's in another directory with a .git
in it.
You can bypass the submodule restriction using git update-index
, but if you do, you're straying into dangerous territory:
$ git hash-object -w dir/sub/foo
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
$ git update-index --add --cacheinfo 100644,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,dir/sub/foo
What happens at this point isn't well defined if dir/sub
really is a Git repository. (I made a temporary pair of repositories to run these commands, and did not check any further here.) Note that ../
is not valid as a path component:
$ git update-index --add --cacheinfo 100644,e69de29bb2d1d6434b8b29ae775ad8c2e48c5391,../sub/foo
error: Invalid path '../sub/foo'
fatal: git update-index: --cacheinfo cannot add ../sub/foo
CodePudding user response:
Please read the important note at the bottom for a better alternative solution!
The literal answer to the question asked
Although you can't, as torek explained very well, there is a workaround.
You can version your file in b
and copy it in a
with a script. Here is your setup:
/base
|- a
| |- .gitignore
|- b
|- copy-file
|- resources
|- file.txt
/base/b/resources/file.txt
is your file that should belong to/base/a
but versionned in/base/b
./base/b/copy-file
is a script that copies the file to the correct location, don't forget to make it executable./base/a/.gitignore
ignoresfile.txt
so that the copied file isn't versionned in/base/a
.
Your workflow is the following:
- Update all your branches.
- Run
/base/b/copy-file
(possibly with git hooks), that will place an unversioned copy of yourfile.txt
in/base/a
. - Start working.
Important note
I know it seems tempting to do it this way, because of reasons that pushed you into that current workflow of yours, but even if I answered your question as is, I also suggest you look into different approaches. For example:
- Keep the
copy-file
script in/base
. There is probably a reason why you haven't done a single project with both those subfolders. That reason must be reusability. If you define the relative path of youra
subdirectory in yourb
repository, that means they are somehow connected and interdependant. Which brings me to the next and better solution: - Use a package manager! I'm sure your language has one of those fancy package managers, they're everywhere! So use
npm
,pip
,composer
or whatever your language works with, make yourb
sub-project require youra
sub-project (or the other way around, it's not really clear what requires what in your question) and use namespaces to reference the distant file, when you need it in the other sub-project. You don't usually need to publish one of your sub-projects to use the official package manager website, you should have a way to include a Git repository.