我正在尝试从目录外部执行 git pull ...
不要那样做。 (你为什么要这么做?)
git --git-dir=$WORKDIR/sources/.git pull
In a comment, ElpieKay suggests:
添加--work-tree=$WORKDIR/sources
你回复的:
现在好像可以了
当你同时使用这两个选项时,Git 会:
- 将自己重新定位到您的工作树,
$WORKDIR/sources;
- 使用
$WORKDIR/sources/.git 作为适当的存储库; 和
- 在那里运行 Git 命令。
除了覆盖任何环境 $GIT_WORK_TREE 和 $GIT_DIR 变量之外,这对选项与执行操作相同:
git -C $WORKDIR/sources pull
其中-C 导致Git 先更改目录,然后再运行git pull。这将是从该位置运行git pull 的更典型方法:具有单独--git-dir 和--work-tree 选项的变体允许您将.git 从工作树中分离出来,在相对罕见的情况下这是有用的,并覆盖任何早期的环境变量设置。1
1当您使用这些选项时,Git 本身会设置这些相同的环境变量。所以:
git --git-dir=A --work-tree=B whatever
工作原理完全一样:
GIT_DIR=A GIT_WORK_TREE=B git whatever
除了后一种形式采用 POSIX 样式的 shell(命令行解释器)。
进一步阅读(可选)
您能否就为什么需要此选项提供任何见解?
Git repository 实际上只是 .git 目录中的东西。存储库主要由两个数据库组成:
每个提交都包含每个文件的完整快照,作为一种只读存档。 Git 会压缩这些快照(以多种方式),并在快照内删除重复的文件,因此在许多情况下这占用的空间非常少。这种压缩技术并不完美——它在存在许多大的、预压缩的二进制文件时往往会失败——但它对于人类可读的文件非常有用,例如软件的源代码。 p>
提交本身也包含其前一个提交的提交编号 - 或数字,复数,用于合并提交。因此,只要 Git 可以找到 last 提交(通过分支或其他名称),Git 就可以使用这些来找到 每一个较早的提交,一次一步,通过向后看的链条。这是存储库中的历史记录:History = 提交,从末尾开始并向后工作。
但有一个问题。这些只读的、压缩的提交/文件只能由 Git 本身使用。你可以用这些做的主要事情是与其他 Git 交换它们。您还可以将它们与git diff 或类似的一起使用,并对项目随时间的变化进行一些分析,等等。但你无法取得任何进展。仅使用由两个数据库组成的存储库,您无法完成新工作。
要完成工作,您需要一个工作树。在这里,您将有 Git extract 提交。提取的提交将归档(压缩、只读、Git 化、无用)文件扩展 成它们正常的日常(有用)形式。我们称之为签出分支或提交。 (我们何时以及是否称其为“分支”与“提交”是很多混乱的根源,因为人类在这里不一致,有时也对细节一无所知。棘手的部分是,当我们有一个branch 签出,我们也有一个 commit 签出。当我们有 only 一个提交签出时——通过 Git 所谓的“分离的 HEAD” “——我们仍然有一个提交被检出,但没有一个分支。)
非裸存储库被定义为具有工作树的存储库。裸存储库是缺少工作树的存储库。基本上就是这些了,但是缺少工作树意味着这个存储库可以接收新的提交无条件。具有工作树的 Git 存储库无法安全地接收已签出分支的新提交。所以服务器(托管)站点通常存储裸仓库。
git pull 命令的意思是:首先,运行 git fetch,然后运行第二个 Git 命令来处理通过 git fetch 步骤获得的新提交。 fetch 步骤在裸存储库中运行良好,但第二个命令(无论您为 git pull 选择哪个命令来运行)需要工作树。
当你运行 Git 命令时,如果你有一个工作树,你应该在工作树内运行它们。如果您有充分的理由希望从该工作树外部 运行git,您可以使用git -C <em>working tree path</em>,如上所示。您也可以使用$GIT_WORK_TREE 或--work-tree 参数。
此外,当您确实有一个工作树并且没有使用所有这些复杂的方法将存储库从工作树中分离出来时,Git 期望存在一个 .git 目录(或文件) 在顶层。事实上,在没有所有这些花哨的两部分分离技巧的情况下,这就是 如何 Git 找到工作树的顶层。假设你在:
/path/to/some/working/dir/ectory
Git 将查看.git 是否存在于此路径中。如果没有,Git 将删除 ectory 部分并重试:有 /path/to/some/working/dir/.git 吗?如果没有,Git 将删除 dir 部分并重试:有 /path/to/some/working/.git 吗?如果是这样,Git 已经找到了您的工作树的顶层,以及此处的 .git — 无论它是一个文件,包含 .git 目录的位置,还是目录本身,因此存在 .git 目录—确定存储库本身所在的位置。
不过,在你的情况下,你跑了:
git --git-dir=$WORKDIR/sources/.git ...
这告诉 Git:Git 目录是(无论 $WORKDIR 扩展为什么——这个扩展是由 shell 完成的,而不是 Git)/sources/.git。所以 Git 不必搜索顶层。你没有告诉Git工作树的顶层在哪里,所以它只是假设你的当前目录是工作树。但实际上,您当前的目录是另一回事。 Git 可能因此损坏了各种文件,理论上它们来自您的工作树。
Git 还存储了一些 Git 称为 index(或 暂存区 或 cache 的东西,这可能会部分拯救你,具体取决于Git 的哪个部分正在执行此“调用”)。这实际上只是存储库目录中的一个文件,例如.git/index。 (文件的确切位置可能会有所不同,有时还有其他文件,所以不要在这一路径上计算太多。请记住.git/index,但如果有一个具体的模型来说明“索引”是什么。)在这个索引中,Git 存储关于它已签出的文件的信息。索引的存在,加上假设您已经在工作树的顶层,这就是 git --git-dir=<path> pull 行为不正确的原因。