致命:磁盘上存在路径“.eslintrc.json”,但 'master~10' 中不存在
fatal: Path '.eslintrc.json' exists on disk, but not in 'master~10'
从开发推送到主控时,测试作业(在 Gitlab 管道中)的阶段分布式任务出现错误。
本地或者开发都没有问题。
我想了解此错误消息的实际含义,这里的“磁盘”是什么以及这个 master~10 到底是什么意思(在谷歌搜索时,我理解它的意思是“将当前推送的分支与所有分支进行比较”父级在 master 中最多提交 10",是否正确,为什么要这样做?)
如何解决这个问题,如何在本地调试?
I'd like to understand what
fatal: Path '.eslintrc.json' exists on disk, but not in 'master~10'
actually mean[s], what is "disk" here and what does this master~10 mean exactly
准确意味着我们需要从一些关键背景开始。
背景
当使用Git时,我们运行:
git checkout somebranch
或:
git switch somebranch
或者有时——CI/CD系统特别喜欢这样做——我们可能会使用:
git checkout <hash-ID>
或:
git switch --detach <hash-ID>
这些命令指示 Git 从某个特定提交中提取源代码树,并使该特定提交成为 当前提交 。该提交的哈希 ID 是我们直接给 Git 的一个 - raw 哈希 ID,如 git 开关 --detach <em>hash-ID</em>
情况——或者当我们使用分支名称时,某些分支名称暗示的情况。
(当我们do使用分支名称时,checkout或switch命令的作用是使它成为当前分支,在使其 most recent 或 tip 提交 current commit 时。当我们使用分离的 HEAD 模式时,我们最终得到 no 分支,但是我们仍然有给定的提交作为 当前提交 。所以我们总是有一个当前提交;我们有一个当前分支名称,当且仅当我们在结帐/切换命令中使用分支名称时。)
Git 以这种方式工作的原因 是 Git 不存储 文件 ,确切地说,也不Git 真的可以与 分支 一起使用吗? Git 商店是 提交 。所有提交都具有唯一的哈希 ID:可以说,这些是它们的“真名”。每个 commit 存储文件:事实上,每个提交存储一整套 every 文件,就像你当时的形式一样(或谁)做出了那个承诺。所以这就是我们如何获取文件 out of Git:它们在每个提交中,我们选择我们想要的提交并获取这些文件。
使用原始哈希 ID 的问题在于它们又大又丑,random-looking 人类通常无法正确处理的事情。人类不喜欢或使用它们。 计算机可以使用它们——计算机擅长这类事情——但人类不会。人们喜欢 names: 分支名称,例如 master
或 main
、develop
、feature/tall
等。这些对人类很有效。因此,除了 snapshots-in-commits——存储为 Git 内部对象的大数据库,由哈希 ID 索引——Git 提供了一个数据库,其中 Git 存储这些名称并将每个名称配对使用单个哈希 ID。
分支名称,特别是,总是表示 最新的 提交“在”该分支上。 Git 使用每个提交中存储的 元数据 将提交本身串在一起,向后。
换句话说,每个提交,根据其唯一的(和random-looking和又大又丑和impossible-for-humans)哈希ID,存储两个事情:
一个提交有一个源快照,更像是一个 tarball 或 WinZip 存档或其他什么。 (然而,与某些存档格式不同,in 快照中的文件以特殊的 Git-only 格式存储,它们不仅被压缩,而且 de-duplicated 反对 所有 次提交,包括这次提交本身。)
一个提交有元数据,或者关于提交本身的信息。例如,元数据包括提交人的姓名。它们包括提交者编写的日志消息。它们包括一些 date-and-time 标记以显示 提交者何时 提交。
为了使 Git 分支工作,Git 在每个提交的元数据中包含一个 previous 提交哈希 ID 的列表。此列表通常只有一个元素长:给出此提交的 parent 提交的哈希 ID。
这些“普通提交”父哈希 ID 的结果是一个简单的线性但 backwards-looking 链。让我们画一个,用简单的单个大写字母替换真正的哈希 ID。我们将把最近的提交——我们将其哈希 ID 称为 H
——放在右边,这里:
... <-F <-G <-H
提交 H
存储快照和元数据,并且在 H
的元数据中,Git 存储了另一个较早提交的哈希 ID。那个散列 ID——在我们的图表中是 G
,但在现实中是一些丑陋的大东西 random-looking——是 Git 对象的大数据库中提交 G
的真实名称,所以Git 可以使用该哈希 ID 提取提交 G
。
提交G
当然是一个提交,所以它既有快照又有元数据,在G
的元数据中,有一个早期提交F
的哈希ID。所以 Git 可以读取 G
来找到 F
的哈希 ID,并使用它来找到 F
本身。
提交 F
当然是一个提交,所以它既有快照又有元数据,而且......好吧,你现在应该知道这是怎么回事了。通过反复阅读一个提交,包括它的元数据,Git 可以通过历史不断备份,一次提交:从 H
我们到达 G
,从那里我们到达 F
,从那里我们到达(大概)E
,依此类推,随着时间倒退。最终我们将到达 有史以来第一次提交,这里将是提交 A
:该提交有一个 empty 列表之前的提交,因为没有之前的提交,所以Git终于可以停止倒退了。
这是存储库中的历史记录:存储库中的提交是历史。我们所要做的就是以某种方式找到 last 提交 H
的原始哈希 ID,然后 Git 可以向后工作。这就是分支名称的用武之地。
为了找到提交H
——最后一次提交——Git存储的哈希ID名称中的最后一次提交。当该名称是 branch 名称时,我们可以将其赋予 git checkout
或 git switch
并“在分支上”。由于名称包含原始哈希 ID,我们将其绘制为箭头,指向提交:
...--G--H <-- master
因为这里的分支名称是master
,名称master
包含提交H
的原始哈希ID,从中Git可以找到更早的提交。
如果我们创建一个 new 分支,我们开始使用指向 一些现有提交 的新名称。我们可以选择任何提交,但通常在这种情况下我们会从 H
开始:
...--G--H <-- develop, master
当我们使用 git checkout
或 git switch
选择其中一个名称时,我们会得到一个 附加的 HEAD,因此 name 是当前的 name:
...--G--H <-- develop (HEAD), master
这意味着我们最近的 checkout/switch 是 develop
。我们有所有文件 来自 提交 H
以处理/使用。
Git 提交中的文件是 read-only. de-duplication / 共享技巧之所以有效,是因为每个提交的所有部分都是完全 read-only(并且只有 Git 实际上可以 读取 存储在提交中的文件),因此 Git 必须 复制在我们可以处理或使用它们之前,将文件从 commit 中移除。将它们复制出来后,这些文件现在可供使用。 Git 此时在您的错误消息中将它们称为“磁盘上”。
鉴于我们正在 on/with 通过 develop
提交 H
,如果我们现在修改一些文件的“磁盘上”副本以及 git add
和 git commit
,我们将得到一个新提交,我们可以将其称为I
,而Git将使名称 develop
指向新提交 I
:
I <-- develop (HEAD)
/
...--G--H <-- master
名称 develop
现在表示 develop
上的最新提交,即提交 I
。名称 master
现在表示 master
上的最新提交,它仍然是提交 H
。如果我们在 develop
上进行第二次新提交,我们将得到:
I--J <-- develop (HEAD)
/
...--G--H <-- master
也就是说,名称 develop
现在指向提交 J
。提交 J
指向提交 I
,后者指向提交 H
,后者指向提交 G
,依此类推。
注意:
现在有 两个 最新提交:H
是最新的(在 master
上),J
是最新的(在 develop
上)。 根据定义, 某些分支名称指向的任何提交都是该分支“上”的最新提交。 Git 通常不会这样做,但我们可以强制名称 master
指向 G
而不是 H
:
H--I--J <-- develop (HEAD)
/
...--G <-- master
如果我们这样做(有理由不这样做!)那么 G
现在是 master
上的最新提交,并且 H-I-J
仅在 develop
上提交。请注意 所有 提交都在 develop
上。如果我们再次将 master
向前移动一跳到 H
,我们将回到之前的设置,提交到 H
,并且 I-J
仅在 develop
].
重要的是提交;分支名称只是为了帮助我们(和 Git)找到 提交。 提交永远不会改变,但分支名称会发生很大变化。 “在”分支上的提交集通常会随着时间的推移而增加:我们添加新的提交,and/or 我们 Git 将分支名称“向前”移动。
如果我们切换回 master
,Git 将从我们的“on-disk”工作区中删除提交 J
的所有文件并放入,相反,来自提交 H
的文件。我们现在可以创建第二个功能分支:
I--J <-- develop
/
...--G--H <-- feature (HEAD), master
并进行两次 更多 提交:
I--J <-- develop
/
...--G--H <-- master
\
K--L <-- feature (HEAD)
我们只能添加 提交到存储库。无法更改现有提交。新提交向后指向现有提交,因此存在历史记录。历史不过是提交,正如从某个分支名称开始并向后工作所发现的那样。提交存储文件和元数据;元数据让历史发挥作用;并且分支名称找到 latest 提交,从中Git 向后工作。
回到你的问题
what is "disk" here and what does this master~10 mean exactly
我们已经了解了“在磁盘上”的含义:Git 已经提取了一个 当前提交 ,并且通过提取文件 from 那个提交,Git 已经在你的工作树中创建了文件。您可能还创建了 new 文件,因为检出或切换操作:在这种情况下,这些文件也在“磁盘上”。
Git 已在您的工作树中找到 .eslint.json
。
master~10
现在可以通过我们绘制的图表进行解释。假设我们有:
I--J <-- develop
/
...--G--H <-- master (HEAD)
\
K--L <-- feature
这意味着我们正在“开启”master
,使用提交 H
。名称 master
的字面意思 意思是 “提交 H
” 每当我们在 Git 需要 commit[ 的上下文中使用它时=334=],比如我们 运行:
git diff master feature
或:
git show master
在这些情况下,我们指示 Git 查看 git diff
命令的提交 H
和 L
,或提交 H
及其git show
命令的父级 G
。
添加波浪号 ~
后缀,后跟可选数字,指示 Git 向后跳转给定次数。该数字默认为 1,但这里我们有 10
,因此这意味着向后移动十次。对于我们的例子来说太多了,所以让我们考虑 master~3
代替:
- 开始于
H
- 后退一次:我们现在在
G
- 再次向后移动:我们现在在
F
,大概(虽然我没有画)
- 第三次后退:我们现在在
E
,大概是
所以 master~3
会 select 提交 E
,假设有关我没有绘制的提交的内容。
同样,feature~3
表示:
- 开始于
L
- 后退一次
K
- 第二次返回
H
- 第三次移回
G
因此这意味着 提交 G
。 develop~3
将从 J
开始,后退三次,并再次在提交 G
结束。
所以这些都是拼写提交哈希 ID 而不必拼写提交哈希 ID 的方法。此外,它们 relative 到分支中的 last 提交(根据定义,因为分支名称始终表示最后一次提交 在分支)。当我们在 分支上进行新提交时,分支变得越来越长,如果我们总是向后移动 3 跳(或 10 跳),我们将始终得到 3(或10) 从 last.
跳回
所以说 .eslintrc.json
不在 master~10
中的错误消息只是意味着您通过 ~10
后缀选择的任何提交都应用于 master
,那个提交里面没有.eslint.json
。 提交中的文件缺少 .eslint.json
文件。
要获取此特定消息,您可能需要 运行:
git diff master~10
这意味着 将通过 master~10
找到的提交中存储的文件与工作树(磁盘上)中的文件进行比较 .
从开发推送到主控时,测试作业(在 Gitlab 管道中)的阶段分布式任务出现错误。 本地或者开发都没有问题。
我想了解此错误消息的实际含义,这里的“磁盘”是什么以及这个 master~10 到底是什么意思(在谷歌搜索时,我理解它的意思是“将当前推送的分支与所有分支进行比较”父级在 master 中最多提交 10",是否正确,为什么要这样做?)
如何解决这个问题,如何在本地调试?
I'd like to understand what
fatal: Path '.eslintrc.json' exists on disk, but not in 'master~10'
actually mean[s], what is "disk" here and what does this master~10 mean exactly
准确意味着我们需要从一些关键背景开始。
背景
当使用Git时,我们运行:
git checkout somebranch
或:
git switch somebranch
或者有时——CI/CD系统特别喜欢这样做——我们可能会使用:
git checkout <hash-ID>
或:
git switch --detach <hash-ID>
这些命令指示 Git 从某个特定提交中提取源代码树,并使该特定提交成为 当前提交 。该提交的哈希 ID 是我们直接给 Git 的一个 - raw 哈希 ID,如 git 开关 --detach <em>hash-ID</em>
情况——或者当我们使用分支名称时,某些分支名称暗示的情况。
(当我们do使用分支名称时,checkout或switch命令的作用是使它成为当前分支,在使其 most recent 或 tip 提交 current commit 时。当我们使用分离的 HEAD 模式时,我们最终得到 no 分支,但是我们仍然有给定的提交作为 当前提交 。所以我们总是有一个当前提交;我们有一个当前分支名称,当且仅当我们在结帐/切换命令中使用分支名称时。)
Git 以这种方式工作的原因 是 Git 不存储 文件 ,确切地说,也不Git 真的可以与 分支 一起使用吗? Git 商店是 提交 。所有提交都具有唯一的哈希 ID:可以说,这些是它们的“真名”。每个 commit 存储文件:事实上,每个提交存储一整套 every 文件,就像你当时的形式一样(或谁)做出了那个承诺。所以这就是我们如何获取文件 out of Git:它们在每个提交中,我们选择我们想要的提交并获取这些文件。
使用原始哈希 ID 的问题在于它们又大又丑,random-looking 人类通常无法正确处理的事情。人类不喜欢或使用它们。 计算机可以使用它们——计算机擅长这类事情——但人类不会。人们喜欢 names: 分支名称,例如 master
或 main
、develop
、feature/tall
等。这些对人类很有效。因此,除了 snapshots-in-commits——存储为 Git 内部对象的大数据库,由哈希 ID 索引——Git 提供了一个数据库,其中 Git 存储这些名称并将每个名称配对使用单个哈希 ID。
分支名称,特别是,总是表示 最新的 提交“在”该分支上。 Git 使用每个提交中存储的 元数据 将提交本身串在一起,向后。
换句话说,每个提交,根据其唯一的(和random-looking和又大又丑和impossible-for-humans)哈希ID,存储两个事情:
一个提交有一个源快照,更像是一个 tarball 或 WinZip 存档或其他什么。 (然而,与某些存档格式不同,in 快照中的文件以特殊的 Git-only 格式存储,它们不仅被压缩,而且 de-duplicated 反对 所有 次提交,包括这次提交本身。)
一个提交有元数据,或者关于提交本身的信息。例如,元数据包括提交人的姓名。它们包括提交者编写的日志消息。它们包括一些 date-and-time 标记以显示 提交者何时 提交。
为了使 Git 分支工作,Git 在每个提交的元数据中包含一个 previous 提交哈希 ID 的列表。此列表通常只有一个元素长:给出此提交的 parent 提交的哈希 ID。
这些“普通提交”父哈希 ID 的结果是一个简单的线性但 backwards-looking 链。让我们画一个,用简单的单个大写字母替换真正的哈希 ID。我们将把最近的提交——我们将其哈希 ID 称为 H
——放在右边,这里:
... <-F <-G <-H
提交 H
存储快照和元数据,并且在 H
的元数据中,Git 存储了另一个较早提交的哈希 ID。那个散列 ID——在我们的图表中是 G
,但在现实中是一些丑陋的大东西 random-looking——是 Git 对象的大数据库中提交 G
的真实名称,所以Git 可以使用该哈希 ID 提取提交 G
。
提交G
当然是一个提交,所以它既有快照又有元数据,在G
的元数据中,有一个早期提交F
的哈希ID。所以 Git 可以读取 G
来找到 F
的哈希 ID,并使用它来找到 F
本身。
提交 F
当然是一个提交,所以它既有快照又有元数据,而且......好吧,你现在应该知道这是怎么回事了。通过反复阅读一个提交,包括它的元数据,Git 可以通过历史不断备份,一次提交:从 H
我们到达 G
,从那里我们到达 F
,从那里我们到达(大概)E
,依此类推,随着时间倒退。最终我们将到达 有史以来第一次提交,这里将是提交 A
:该提交有一个 empty 列表之前的提交,因为没有之前的提交,所以Git终于可以停止倒退了。
这是存储库中的历史记录:存储库中的提交是历史。我们所要做的就是以某种方式找到 last 提交 H
的原始哈希 ID,然后 Git 可以向后工作。这就是分支名称的用武之地。
为了找到提交H
——最后一次提交——Git存储的哈希ID名称中的最后一次提交。当该名称是 branch 名称时,我们可以将其赋予 git checkout
或 git switch
并“在分支上”。由于名称包含原始哈希 ID,我们将其绘制为箭头,指向提交:
...--G--H <-- master
因为这里的分支名称是master
,名称master
包含提交H
的原始哈希ID,从中Git可以找到更早的提交。
如果我们创建一个 new 分支,我们开始使用指向 一些现有提交 的新名称。我们可以选择任何提交,但通常在这种情况下我们会从 H
开始:
...--G--H <-- develop, master
当我们使用 git checkout
或 git switch
选择其中一个名称时,我们会得到一个 附加的 HEAD,因此 name 是当前的 name:
...--G--H <-- develop (HEAD), master
这意味着我们最近的 checkout/switch 是 develop
。我们有所有文件 来自 提交 H
以处理/使用。
Git 提交中的文件是 read-only. de-duplication / 共享技巧之所以有效,是因为每个提交的所有部分都是完全 read-only(并且只有 Git 实际上可以 读取 存储在提交中的文件),因此 Git 必须 复制在我们可以处理或使用它们之前,将文件从 commit 中移除。将它们复制出来后,这些文件现在可供使用。 Git 此时在您的错误消息中将它们称为“磁盘上”。
鉴于我们正在 on/with 通过 develop
提交 H
,如果我们现在修改一些文件的“磁盘上”副本以及 git add
和 git commit
,我们将得到一个新提交,我们可以将其称为I
,而Git将使名称 develop
指向新提交 I
:
I <-- develop (HEAD)
/
...--G--H <-- master
名称 develop
现在表示 develop
上的最新提交,即提交 I
。名称 master
现在表示 master
上的最新提交,它仍然是提交 H
。如果我们在 develop
上进行第二次新提交,我们将得到:
I--J <-- develop (HEAD)
/
...--G--H <-- master
也就是说,名称 develop
现在指向提交 J
。提交 J
指向提交 I
,后者指向提交 H
,后者指向提交 G
,依此类推。
注意:
现在有 两个 最新提交:
H
是最新的(在master
上),J
是最新的(在develop
上)。 根据定义, 某些分支名称指向的任何提交都是该分支“上”的最新提交。 Git 通常不会这样做,但我们可以强制名称master
指向G
而不是H
:H--I--J <-- develop (HEAD) / ...--G <-- master
如果我们这样做(有理由不这样做!)那么
G
现在是master
上的最新提交,并且H-I-J
仅在develop
上提交。请注意 所有 提交都在develop
上。如果我们再次将master
向前移动一跳到H
,我们将回到之前的设置,提交到H
,并且I-J
仅在develop
].重要的是提交;分支名称只是为了帮助我们(和 Git)找到 提交。 提交永远不会改变,但分支名称会发生很大变化。 “在”分支上的提交集通常会随着时间的推移而增加:我们添加新的提交,and/or 我们 Git 将分支名称“向前”移动。
如果我们切换回 master
,Git 将从我们的“on-disk”工作区中删除提交 J
的所有文件并放入,相反,来自提交 H
的文件。我们现在可以创建第二个功能分支:
I--J <-- develop
/
...--G--H <-- feature (HEAD), master
并进行两次 更多 提交:
I--J <-- develop
/
...--G--H <-- master
\
K--L <-- feature (HEAD)
我们只能添加 提交到存储库。无法更改现有提交。新提交向后指向现有提交,因此存在历史记录。历史不过是提交,正如从某个分支名称开始并向后工作所发现的那样。提交存储文件和元数据;元数据让历史发挥作用;并且分支名称找到 latest 提交,从中Git 向后工作。
回到你的问题
what is "disk" here and what does this master~10 mean exactly
我们已经了解了“在磁盘上”的含义:Git 已经提取了一个 当前提交 ,并且通过提取文件 from 那个提交,Git 已经在你的工作树中创建了文件。您可能还创建了 new 文件,因为检出或切换操作:在这种情况下,这些文件也在“磁盘上”。
Git 已在您的工作树中找到 .eslint.json
。
master~10
现在可以通过我们绘制的图表进行解释。假设我们有:
I--J <-- develop
/
...--G--H <-- master (HEAD)
\
K--L <-- feature
这意味着我们正在“开启”master
,使用提交 H
。名称 master
的字面意思 意思是 “提交 H
” 每当我们在 Git 需要 commit[ 的上下文中使用它时=334=],比如我们 运行:
git diff master feature
或:
git show master
在这些情况下,我们指示 Git 查看 git diff
命令的提交 H
和 L
,或提交 H
及其git show
命令的父级 G
。
添加波浪号 ~
后缀,后跟可选数字,指示 Git 向后跳转给定次数。该数字默认为 1,但这里我们有 10
,因此这意味着向后移动十次。对于我们的例子来说太多了,所以让我们考虑 master~3
代替:
- 开始于
H
- 后退一次:我们现在在
G
- 再次向后移动:我们现在在
F
,大概(虽然我没有画) - 第三次后退:我们现在在
E
,大概是
所以 master~3
会 select 提交 E
,假设有关我没有绘制的提交的内容。
同样,feature~3
表示:
- 开始于
L
- 后退一次
K
- 第二次返回
H
- 第三次移回
G
因此这意味着 提交 G
。 develop~3
将从 J
开始,后退三次,并再次在提交 G
结束。
所以这些都是拼写提交哈希 ID 而不必拼写提交哈希 ID 的方法。此外,它们 relative 到分支中的 last 提交(根据定义,因为分支名称始终表示最后一次提交 在分支)。当我们在 分支上进行新提交时,分支变得越来越长,如果我们总是向后移动 3 跳(或 10 跳),我们将始终得到 3(或10) 从 last.
跳回所以说 .eslintrc.json
不在 master~10
中的错误消息只是意味着您通过 ~10
后缀选择的任何提交都应用于 master
,那个提交里面没有.eslint.json
。 提交中的文件缺少 .eslint.json
文件。
要获取此特定消息,您可能需要 运行:
git diff master~10
这意味着 将通过 master~10
找到的提交中存储的文件与工作树(磁盘上)中的文件进行比较 .