Git pull 不起作用,显示本地文件已修改但未修改
Git pull doesn't work and shows local files as modified with no modifications
我正在尝试从目录外执行 git 拉取,我是 运行 这个命令:
git --git-dir=$WORKDIR/sources/.git pull
输出是“Alrady Up To Date”或者它只是“拉取”修改但文件不是远程文件,即使 git 拉取输出显示它应该是, git状态显示文件已“修改”,就好像他在git pull后保留本地版本并告诉我我修改了它。
我该如何解决这个问题?我了解了 --work-tree 选项,但我不知道它是否会以某种方式产生影响。
I am trying to perform a git pull from outside the directory ...
不要那样做。 (你为什么要这么做?)
git --git-dir=$WORKDIR/sources/.git pull
Add --work-tree=$WORKDIR/sources
您回复的内容:
Seems to be working now
当您同时使用这两个选项时,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
当您使用这些选项时,1Git 本身会设置这些相同的环境变量。所以:
git --git-dir=A --work-tree=B whatever
与以下内容完全相同:
GIT_DIR=A GIT_WORK_TREE=B git whatever
除了后一种形式采用 POSIX 风格 shell(命令行解释器)。
进一步阅读(可选)
can you provide any insight on why this option is needed?
A Git repository 实际上只是 .git
目录中的东西。存储库主要由两个数据库组成:
一个——通常更大——由Git的提交和其他内部对象组成。这些通过它们的散列 ID 进行编号和检索。 提交 哈希 ID 尤其总是唯一的,要检索提交,Git 需要知道它的编号。
另一个数据库由names,如b运行ch和tag names组成,每一个都映射到一个hash ID号。这允许您使用 b运行ch 或标记名称来检索提交。添加 new 提交通常涉及更新 b运行ch 名称或远程跟踪名称,以便能够找到新的提交。
每个提交都包含每个文件的完整快照,作为一种只读存档。 Git 压缩这些快照(以多种方式)并在 快照中删除重复的文件 ,因此在许多情况下这需要非常少的 space。这种压缩技术并不完美——它在存在许多大的、预压缩的二进制文件时往往会失败——但它非常适合 人类可读的 文件,例如软件的源代码.
提交本身也包含提交编号——或者数字,复数,用于合并提交——它们的前身提交.因此,只要 Git 可以找到 last 提交(通过 b运行ch 或其他名称),Git 就可以使用这些来找到 每个较早的提交,一次一步,通过向后看的链。这是存储库中的历史记录:History = commits,从最后开始并向后工作。
但是有一个问题。这些只读、压缩的 commits/files 只能由 Git 本身使用 。你可以用这些做的主要事情是与其他一些 Git 交换它们。您还可以将它们与 git diff
或类似的方法一起使用,并对项目随时间发生的变化进行一些分析,等等。但是你无法取得任何进展。您无法完成 new 工作,只有由两个数据库组成的存储库。
要完成工作,您需要一个工作树。在这里,您将 Git 提取 提交。提取的提交将归档(压缩的、只读的、Git-化的、无用的)文件扩展到他们正常的日常(有用的)形式。我们称之为 checked out b运行ch 或提交。 (我们何时以及是否将其称为“b运行ch”与“提交”是很多混乱的根源,因为人类在这里不一致,有时会忽略运行t的细节棘手的部分是,当我们检出 b运行ch 时,我们也会检出 commit。当我们 只有 检出一个提交时——通过 Git 所谓的“分离的 HEAD”——我们仍然有一个检出的提交,但不是 b运行ch .)
非裸存储库被定义为具有工作树的存储库。裸存储库是缺少工作树的存储库。这基本上就是全部内容,但是缺少工作树意味着这个存储库可以 接收 新提交 无条件地 。具有工作树的 Git 存储库无法安全地接收已签出的 b运行ch 的新提交。所以 server (hosting) 站点通常存储裸存储库。
git pull
命令意味着:首先,运行git fetch
,然后运行第二个Git命令用通过 git fetch
步骤获得 的新提交。 提取步骤在裸存储库中工作正常,但第二个命令 - 无论您为 git pull
到 运行— 需要 工作树。
当您 运行 Git 命令时,如果您有一个工作树,您应该 运行 它们 在 工作树中.如果有充分的理由你想从 外部 那个工作树 运行 git
,你可以使用 git - C<em>工作树路径</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
行为不正确的原因。
我正在尝试从目录外执行 git 拉取,我是 运行 这个命令:
git --git-dir=$WORKDIR/sources/.git pull
输出是“Alrady Up To Date”或者它只是“拉取”修改但文件不是远程文件,即使 git 拉取输出显示它应该是, git状态显示文件已“修改”,就好像他在git pull后保留本地版本并告诉我我修改了它。
我该如何解决这个问题?我了解了 --work-tree 选项,但我不知道它是否会以某种方式产生影响。
I am trying to perform a git pull from outside the directory ...
不要那样做。 (你为什么要这么做?)
git --git-dir=$WORKDIR/sources/.git pull
Add
--work-tree=$WORKDIR/sources
您回复的内容:
Seems to be working now
当您同时使用这两个选项时,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
当您使用这些选项时,
1Git 本身会设置这些相同的环境变量。所以:
git --git-dir=A --work-tree=B whatever
与以下内容完全相同:
GIT_DIR=A GIT_WORK_TREE=B git whatever
除了后一种形式采用 POSIX 风格 shell(命令行解释器)。
进一步阅读(可选)
can you provide any insight on why this option is needed?
A Git repository 实际上只是 .git
目录中的东西。存储库主要由两个数据库组成:
一个——通常更大——由Git的提交和其他内部对象组成。这些通过它们的散列 ID 进行编号和检索。 提交 哈希 ID 尤其总是唯一的,要检索提交,Git 需要知道它的编号。
另一个数据库由names,如b运行ch和tag names组成,每一个都映射到一个hash ID号。这允许您使用 b运行ch 或标记名称来检索提交。添加 new 提交通常涉及更新 b运行ch 名称或远程跟踪名称,以便能够找到新的提交。
每个提交都包含每个文件的完整快照,作为一种只读存档。 Git 压缩这些快照(以多种方式)并在 快照中删除重复的文件 ,因此在许多情况下这需要非常少的 space。这种压缩技术并不完美——它在存在许多大的、预压缩的二进制文件时往往会失败——但它非常适合 人类可读的 文件,例如软件的源代码.
提交本身也包含提交编号——或者数字,复数,用于合并提交——它们的前身提交.因此,只要 Git 可以找到 last 提交(通过 b运行ch 或其他名称),Git 就可以使用这些来找到 每个较早的提交,一次一步,通过向后看的链。这是存储库中的历史记录:History = commits,从最后开始并向后工作。
但是有一个问题。这些只读、压缩的 commits/files 只能由 Git 本身使用 。你可以用这些做的主要事情是与其他一些 Git 交换它们。您还可以将它们与 git diff
或类似的方法一起使用,并对项目随时间发生的变化进行一些分析,等等。但是你无法取得任何进展。您无法完成 new 工作,只有由两个数据库组成的存储库。
要完成工作,您需要一个工作树。在这里,您将 Git 提取 提交。提取的提交将归档(压缩的、只读的、Git-化的、无用的)文件扩展到他们正常的日常(有用的)形式。我们称之为 checked out b运行ch 或提交。 (我们何时以及是否将其称为“b运行ch”与“提交”是很多混乱的根源,因为人类在这里不一致,有时会忽略运行t的细节棘手的部分是,当我们检出 b运行ch 时,我们也会检出 commit。当我们 只有 检出一个提交时——通过 Git 所谓的“分离的 HEAD”——我们仍然有一个检出的提交,但不是 b运行ch .)
非裸存储库被定义为具有工作树的存储库。裸存储库是缺少工作树的存储库。这基本上就是全部内容,但是缺少工作树意味着这个存储库可以 接收 新提交 无条件地 。具有工作树的 Git 存储库无法安全地接收已签出的 b运行ch 的新提交。所以 server (hosting) 站点通常存储裸存储库。
git pull
命令意味着:首先,运行git fetch
,然后运行第二个Git命令用通过 git fetch
步骤获得 的新提交。 提取步骤在裸存储库中工作正常,但第二个命令 - 无论您为 git pull
到 运行— 需要 工作树。
当您 运行 Git 命令时,如果您有一个工作树,您应该 运行 它们 在 工作树中.如果有充分的理由你想从 外部 那个工作树 运行 git
,你可以使用 git - C<em>工作树路径</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
行为不正确的原因。