git:如何将外部目录添加到代码库?

68

我想将一个外部目录添加到现有的代码库中。

外部目录: /home/some/directory

工作目录: /htdocs/.git

如果我在/htdocs目录下执行以下命令:

git add /home/some/directory

会出现错误提示: fatal: '/home/some/directory' is outside repository


你实际上想要什么?在我看来,你似乎想要在你的存储库中有些东西,但又不想在你的存储库中有些东西。 - jdizzle
外部目录本身是否是您想合并日志的存储库? - saeedgnu
2
请参见https://dev59.com/M1jUa4cB1Zd3GeqPQl_L,其中包含与Git存储库中的工作树相关的问题。 - basZero
10个回答

67

如果我需要这样做的话,通常会将外部文件或目录移动到我的 git 存储库中,并使用符号链接将其原始位置链接到新位置。

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

在我开发一个插件,并想将其存储在特定位置且保持版本控制的应用程序中时,我使用这种技术。


1
在我的Mac OS X 10.10.3上完全不起作用。基本上,WordPress无法识别符号链接的插件目录或文件,并且它们不会出现在WP插件列表中。我错过了什么吗? - Adam Christianson
有关编程的内容:使用smb共享有什么想法吗?我想使用git同步Firefox书签。 - Matthis Kohli
太棒了。我之前尝试过在另一个方向上创建符号链接,但是 Git 报错了。 ;) - zx81
如果您想复制/打包/压缩 /home/some 中的所有内容,那该怎么办呢? 在这种情况下,您最终只会得到链接,而丢失了实际的内容。 - JUNPA
为了清晰起见:外部文件不在与git仓库相同的文件结构中。因此,实际文件被移动到仓库目录结构(htdocs)中,而不是在仓库内创建符号链接。创建符号链接以便其他应用程序或工作流可以在home/some...上运行。 - satchel

26

我遇到了同样的错误...搜索了很多,但没有得到太多有用的信息。

Christian的回答解决了问题:

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

但是"工作树"让我有些困惑。我在所有的 Git 文档中使用 grep 命令,并找到了 core.worktree

我使用了

git config --global core.worktree /

完成了!现在我可以从任何目录添加了。不知道是否会在其他地方导致问题,但我会随时更新。


1
你是不是想写成“我现在可以从任何目录中添加。”?只是好奇,内心的编辑想要大力修改你的回答。:P - Will Lanni
3
是的,我有轻度的诵读障碍,这会导致你的大脑在完成段落后做其他事情,而你的手指仍停留在中间。(回复迟了很抱歉) - MotherDawg
所以我不能做 git add * :P - Nishant
我不确定发生了什么事情,但在尝试后,GitHub无法再找到我的存储库,然后崩溃了。 - StarSweeper
类似的答案 https://dev59.com/JHE95IYBdhLWcg3wRLwt#8040817 中还有其他关于 git --work-tree=/ add /home/some/directory 的评论。 - XavierStuvw
2
在小心谨慎的前提下,最好不要在“/”上进行实验,而是选择一个位于“/home/user”目录内的测试目录。此外,使用“--local”来玩转您的本地repo(默认情况下),而不是“--global”。 - XavierStuvw

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

4
这里有一些解释: https://dev59.com/am435IYBdhLWcg3wrSBB 尽管对我来说不太清楚如果有人克隆了那个仓库会得到什么。 - Sam Hasler
这也使得编写 .gitignore 变得非常复杂,而且 git status 和 git add --a 将删除 git 工作目录之外的文件。你可以将工作目录设置为本地存储库设置,但默认情况下会监视设置目录下的所有内容。这又需要 .gitignore 的帮助。比它值得的麻烦多了。 - Ray Foss
请参考此讨论板块中 https://dev59.com/JHE95IYBdhLWcg3wRLwt#8626989 的其他评论,以了解此解决方案的更多信息。 - XavierStuvw
如何在Android上排除/storage/sdcard1/.android_secure?在已经root的手机上,git --work-tree=/ add /storage/sdcard1 并不能起作用。 - Khurshid Alam

10

这个问题有一个非常简单的解决方案。

假设你的Git仓库在 /var/data/my-app 中,你想要将 /var/data/public/ 添加到该仓库中。因为Git不会添加根目录之外的资源,所以您无法使用 'add' 命令来添加资源。

解决方案:

  1. 将 /var/data/public/ 目录移动到 Git 仓库根目录(/var/data/my-app)中。

  2. 在 /var/data/public 目录下创建一个符号链接(symbolic link),链接到 /var/data/my-app/public 文件夹,使用命令: ln -s 源文件或目录 虚拟文件或目录

然后,只需按照正常方式使用 git add 命令将移动后的文件或目录添加到 Git 中。现在,您的 Git 源代码控制正在跟踪所需的文件/文件夹,而您在外部目录中的符号链接确保该文件/文件夹对于其他任何东西都是可访问的!


1
这实际上并没有跟踪目标目录中的任何内容,它只是跟踪链接。对吗? - incandescentman
@PeterSalazar 不用,因为Stormbytes建议将目标目录移动到git仓库中。符号链接维护原始位置。如果您在仓库中添加了链接,则是正确的。 - shiri
1
如果有多个用户在同一台机器上为同一个git项目做出贡献,那么这种方法就不太可行。例如: 假设在同一台机器上有两个用户:U和T。 U将_/var/linked_目录符号链接到其主文件夹中的某个位置。 另一个用户T想要编辑_/var/linked_目录中的某个文件,但他必须拥有该文件的权限。 即使T对U的链接目录具有写入权限,T也将从U的存储库中编辑工作副本。 - gallo
我有一些我编写的必要 DLL 文件,它们存放在一个外部文件夹中。我在 Visual Studio 中关闭了解决方案,将该文件夹复制到我的解决方案文件夹中,重新打开了项目,并通过 Git 注册了添加的文件夹作为变更。我给变更打了标签并点击了提交。现在我需要的文件已经在代码库中了。 - Alan

4

如果你想要添加到你的代码库中的代码不是太大,你也可以在每次推送之前自动将它复制到你的代码库中。

例如,我需要一个R文件,在多个代码库中经常进行修改,因此我编写了一个小shell脚本:

#!/usr/bin/env bash

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

我运行了这个脚本来推送所有更改,包括/some/directory中的更改。


我喜欢这个解决方案,虽然在文件复制之前可能不是最新的,但它保持了 git 的副本,干净、简单,并且对于克隆仓库的任何人来说都是可预测的。更好的想法可能是将“同步”脚本包含在仓库本身中,也许还有一个相应的“恢复”脚本。 - Kareem

1
这让我想到,我非常希望能够使用符号链接文件/目录的解决方案,但我卡在了Windows电脑上。据我所知,Windows中的符号链接并不真正按照同样的方式工作。因此,另一个解决方案可能是编写两个脚本/ bash函数来“导入”和“导出”相关文件,例如:
import() {
    cp -fr /home/some/directory /htdocs/
}

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

那么你就会在你的代码库中有一个文件副本,你可以使用 git add 命令添加它。


1
我会对外部目录中的每个文件进行硬链接。 由于硬链接不会对原始文件产生额外负担,所以它可以实现完美同步。 唯一的问题是目录不能被链接(只有超级用户才能链接),因此必须创建一个用于存储文件的目录。
例如,通常 zeppelin 只支持笔记本文件的版本控制,但我添加了如下父目录中配置文件的硬链接:
.
├── 2A94M5J1Z
│   └── note.json
├── 2G2U2ZR1T
│   └── note.json
├── conf
│   ├── shiro.ini
│   ├── zeppelin-env.sh
│   └── zeppelin-site.xml
└── README.md

0

如果你想在不同的git仓库之间工作,可以使用子模块(ln不能以这种方式工作)。尝试使用“man git-submodule”命令。


我只是匆匆一瞥,但是将子模块放在父存储库之外看起来比只有两个存储库更丑陋,特别是对于从带有外部子模块的存储库拉取的人。你(或任何人)真正使用过这个吗? - mikeLundquist

-1

如果您使用Windows Git Bash终端,请使用此代码移动目录并创建源的符号链接

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

-3

在代码库中添加一个目录的符号链接,然后再添加相同的目录。

ln -s /home/some/directory/
git add directory

5
但这实际上没有追踪目标目录中的任何内容,它只是追踪链接。 - William Pursell
那么,我如何递归地跟踪目标目录下的所有内容? - Sly
它只是跟踪链接,如上面的回复所述,如果其他人克隆了存储库,他们会得到指向“无处”(甚至更糟的是,“某个地方”)的链接。 - Tomas Pruzina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接