为什么提交一个文件,但所有文件都在 RStudio 中提交?
Why Commiting one file, but all files are committed in RStudio?
我在 Github 上有一个存储库,里面有一些文件,我在 RStudio 服务器上有一个文件夹,里面也有一些文件。我对一些文件做了一些更改,但我只想使用命令
提交一个文件(test.Rmd)
git init
git add test.Rmd
git commit -m "Adding some plots"
git push
而不是仅提交此文件,而是提交文件 test.Rmd 所在文件夹中的所有文件。为什么会这样?我尝试对不同文件夹中的另一个文件执行完全相同的操作,并且提交成功了。在此之前,似乎我已经做了一些事情,比如
git init
git add .
这就是它添加目录中所有文件的原因?
使用 git status
结果
我现在怀疑问题是取消添加这些大文件?我想我在最后使用 git push
时不知不觉地提交了所有文件的所有更改。
你的问题充其量是模棱两可的,并且包含一些错误的假设,所以这个答案很长。
一些关于 Git 提交和 git init
的背景
Git 中的所有提交始终包含所有文件。这就是 Git 本身的工作原理。
运行 git init
将:
- 在当前工作目录中创建一个新的空 Git 存储库,或者
- 重新初始化现有的 Git 存储库。
你得到 second 行为——重新初始化现有的 Git 存储库——如果 Git 发现你在一些现有的 Git 存储库。 git init
的输出告诉你它做了哪一个:
$ git init
Initialized empty Git repository in [path, redacted]
$ git init
Reinitialized existing Git repository in [path, redacted]
除了一些几乎肯定不适用于您使用方式的特殊情况外 Git,“重新初始化”变体实际上根本没有做任何事情:您现有的存储库保持不变。
当 git init
创建一个新的、完全空的存储库时,没有提交,因此还没有 b运行ches。因此,您所做的 next 提交是第一次提交。这个提交有点特殊:它是一个 root 提交,没有历史记录。它包含您告诉 Git 要包含的任何文件,使用 git add
.
不过,在这一点之后,您将拥有一个包含现有提交的现有 Git 存储库。这包括您使用 git clone
将一些现有存储库(例如,从 GitHub)复制到您自己机器(例如,您的笔记本电脑)上的新 Git 存储库的情况。你会告诉 Git 检查 一些特定的提交——通常是一些 b运行ch name 的提示提交—这意味着 Git 将使用提交的 来自 的所有文件填充其暂存区和您的工作树。
随后,您将编辑一些文件,甚至可能创建一些新文件。然后您 运行 git add
处理一个或多个这些文件。如果您正在 git add
-ing 一个 已经存在 在 Git 的暂存区中的文件,Git 会从其暂存区中丢弃旧副本area 并用你的工作树制作的新副本覆盖暂存区副本。或者,如果您 git add
一个全新的文件,Git 将文件 复制到 其暂存区,作为一个新文件。
在所有这些情况下,暂存区中的所有现有文件都保留在那里。您的下一个 git commit
需要 全部 Git 暂存区中的文件,并从中制作快照。
一个具体的例子
假设你有一个现有的存储库,其中主要的 b运行ch(不管它的名字是什么:GitHub 现在鼓励人们使用 main
而旧的存储库倾向于使用 master
) 在其最近的提交中有十个文件。你 git clone
把这个存储库放到你的笔记本电脑上,所以你的笔记本电脑 Git 软件(“你的 Git”)检查最后一次提交,将十个文件提取到 Git 的暂存中区域和你的工作树。
您现在更改工作树中十个文件中的 五个,但是 运行 git add
仅 一个[=198] =] 五个更新的文件。这意味着您的 Git 的暂存区中有十个文件:九个文件与 当前提交 中的一个匹配,一个与您的 [=127= 中的更新文件匹配]工作树。四个暂存区文件不同于对应的四个工作树文件;其余六个暂存区文件与其对应的工作树匹配。
如果您现在 运行 git commit -m haaaaaands
,您将获得包含十个文件的新提交 与它们现在出现在暂存区中的完全一样 。您的工作树中仍然有所有更新的工作树文件,但是暂存区副本仍然与先前提交的副本匹配,因此新提交的副本与旧提交的副本匹配,除了您 运行 git add
.
您刚刚进行的新提交 成为 当前 提交,这是您笔记本电脑存储库中当前的最新提交b运行ch。您现在可以使用 git push
将此 commit 发送到 GitHub 存储库;如果你最终这样做了,他们收到的提交将逐位匹配存储在笔记本电脑存储库中的 Git 提交。它将具有 9 个文件匹配一个文件不匹配的情况;他们获得的提交将以先前的提交作为其父提交;等等。
关于 git status
的一些知识
首先,git status
会告诉您有关 当前 b运行ch 的信息。它会说类似 on branch main
的内容。这是你的 Git 告诉你你的笔记本电脑存储库有 main
作为 当前 b运行ch。您的 Git 也可能告诉您您“领先” and/or “落后”其他名称,例如 origin/main
:这使用 完全存储在本地的信息 ,在你的笔记本电脑上。此信息可能已过时,具体取决于其他 Git 存储库在 GitHub 上或其他任何地方的活跃程度。
接下来,如果您不在冲突合并的中间——如果您在,剩下的会变得更复杂——git status
命令 运行s two 比较:
首先,它将当前提交中的文件与暂存区中的文件进行比较。其中一些文件通常会完全匹配,因为自从它们从某个提交中提取后您没有对它们进行任何操作。对于那些文件,您的 Git 什么也没说。
暂存区中的其他文件不会匹配您当前的提交,因为例如您运行 git add
在它们上面。在这种情况下,您的 Git 会说这些文件 暂存用于提交 。这只是意味着暂存区副本在某些方面不同于当前提交的副本。
请注意,暂存区中的一些文件可能是新的。也就是说,这些文件根本不存在于 current 提交中。对于这些文件,Git 会说这些是“新文件”。
已列出文件“暂存以供提交”,或未找到任何要列出的文件,您的 Git 现在继续将暂存区中的文件与工作区中的文件进行比较树。和以前一样,一些文件可能匹配。其他文件可能不同 — 甚至您的工作树中的一些文件在暂存区中根本没有对应文件:和以前一样是新文件。
不过这一次,您的 Git 只会告诉您有关 已更改的 个文件,并表示此类文件 未暂存提交 。它确实也收集了每个 new 文件的列表,但将它们推迟到下一部分。
列出所有“未准备提交”的文件后,您的 Git 继续告诉您 未跟踪的文件 。这些是您的工作树中 不在 Git 暂存区中的任何文件。换句话说,这些是“新”文件。
关于这些的奇怪之处在于它们是如何分离出来的,作为一个单独的类别进入“未跟踪”。这样做的原因是 Git 作者 期望 大量 的未跟踪文件 不应该此处报道。 Git 特别适用于创建“目标文件”和其他“构建工件”的编译器,虽然它们可能很重要,但不应添加到提交中并因此永远保存。1
就此而言,Git 通过 .gitignore
和其他排除文件提供了排除功能。在这里,您列出 Git 应该 关闭 ____ up 的文件。它应该而不是抱怨这些未跟踪的文件未被跟踪。此外,当这些文件 未被跟踪时,您可以使用 git add
操作,例如 git add .
,添加 all 未跟踪的文件...除了标记为“忽略”的文件。
.gitignore
的误导是它不会忽略 任何 跟踪 的文件。这里的tracked这个词是根据untracked的定义对立定义的。 未跟踪 文件是存在于您的工作树中但不在Git 的索引中的文件。 tracked 文件是 Git 索引中的文件,无论它是否存在于 Git 索引中。永远不会忽略跟踪的文件。
.gitignore
文件的良好维护使 Git 使用起来更加愉快:git status
告诉你只有 有用的东西; git add .
仅添加 正确的 项。
1这样做的原因是构建工件——至少,理想情况下——完全可以从原始来源复制。我们只想保存 originals,而不是派生的工作产品。这至少可以节省大量的 space 以及以后的时间和人工工作。注意,这里有很多“理想”和“潜力”。这些事情并不总是按计划进行,有时保存所有内容实际上是合理的。 Git 在这方面不是很好,所以您可能不想为此目的使用 Git。
“所有文件始终提交”的可能来源
如果你 运行 git add .
,你是在告诉 Git:扫描我当前的工作目录,找到所有更新的文件和所有新文件以及任何删除的文件,并在每个副本上使用 git add
来更新您的临时区域副本 。此处唯一的例外是 .gitignore
中列出的文件或其他尚未跟踪的排除文件。
如果您 运行 git add *
,行为在某种程度上取决于您的命令行解释器:Unix 风格的 CLI(例如 bash 或 zsh)具有 shell 扩展 *
,而 MS-DOS 风格的 CLI(例如 CMD.EXE)将文字星号 *
传递给 Git,这然后扩展 *
。我不会在这里详细讨论 all 差异的细节,但这往往会大量添加很多或所有文件,具体取决于许多细节。
如果你 运行 git add -u
,你告诉 Git 找到 更新的 文件并添加它们。
您可以有一个预提交挂钩。 Git 中的挂钩相当复杂,但某些软件安装程序不仅会为您安装 Git,还会设置某种自动创建挂钩的功能。 (这是一种重新初始化 Git 存储库 可以 产生影响的设置,尽管要这样做,安装程序必须将这些挂钩放入 Git “模板”,似乎很少使用。)预提交挂钩 可以 ,取决于您 运行 git commit
, 运行 git add
给你,即使你不想要。
如果你 运行 git commit -a
,你实际上是在告诉 Git 到 运行:
git add -u
git commit
这里有一个与预提交挂钩的交互,所以两个命令的顺序并不完全相同,但这可能是您问题的根源。
我已经通过对大文件使用 Git lfs 解决了这个问题。由于我使用的是 RStudio 服务器,我要求管理员安装 Git lfs 然后我执行这些
git lfs install
git lfs track "*.h5ad, *.h5Seurat"
git add .gitattributes
git lfs migrate info
git lfs migrate info --everything
git lfs migrate import --everything --a #override changes in your working copy?
[Y/n] Y
然后它将提交推送到 Github。请注意,*.h5ad 和 *h5Seurat 是我希望 Git lfs 处理的大文件扩展名。
我正在关注这个 link git lfs
我在 Github 上有一个存储库,里面有一些文件,我在 RStudio 服务器上有一个文件夹,里面也有一些文件。我对一些文件做了一些更改,但我只想使用命令
提交一个文件(test.Rmd)git init
git add test.Rmd
git commit -m "Adding some plots"
git push
而不是仅提交此文件,而是提交文件 test.Rmd 所在文件夹中的所有文件。为什么会这样?我尝试对不同文件夹中的另一个文件执行完全相同的操作,并且提交成功了。在此之前,似乎我已经做了一些事情,比如
git init
git add .
这就是它添加目录中所有文件的原因?
使用 git status
结果
我现在怀疑问题是取消添加这些大文件?我想我在最后使用 git push
时不知不觉地提交了所有文件的所有更改。
你的问题充其量是模棱两可的,并且包含一些错误的假设,所以这个答案很长。
一些关于 Git 提交和 git init
的背景
Git 中的所有提交始终包含所有文件。这就是 Git 本身的工作原理。
运行 git init
将:
- 在当前工作目录中创建一个新的空 Git 存储库,或者
- 重新初始化现有的 Git 存储库。
你得到 second 行为——重新初始化现有的 Git 存储库——如果 Git 发现你在一些现有的 Git 存储库。 git init
的输出告诉你它做了哪一个:
$ git init
Initialized empty Git repository in [path, redacted]
$ git init
Reinitialized existing Git repository in [path, redacted]
除了一些几乎肯定不适用于您使用方式的特殊情况外 Git,“重新初始化”变体实际上根本没有做任何事情:您现有的存储库保持不变。
当 git init
创建一个新的、完全空的存储库时,没有提交,因此还没有 b运行ches。因此,您所做的 next 提交是第一次提交。这个提交有点特殊:它是一个 root 提交,没有历史记录。它包含您告诉 Git 要包含的任何文件,使用 git add
.
不过,在这一点之后,您将拥有一个包含现有提交的现有 Git 存储库。这包括您使用 git clone
将一些现有存储库(例如,从 GitHub)复制到您自己机器(例如,您的笔记本电脑)上的新 Git 存储库的情况。你会告诉 Git 检查 一些特定的提交——通常是一些 b运行ch name 的提示提交—这意味着 Git 将使用提交的 来自 的所有文件填充其暂存区和您的工作树。
随后,您将编辑一些文件,甚至可能创建一些新文件。然后您 运行 git add
处理一个或多个这些文件。如果您正在 git add
-ing 一个 已经存在 在 Git 的暂存区中的文件,Git 会从其暂存区中丢弃旧副本area 并用你的工作树制作的新副本覆盖暂存区副本。或者,如果您 git add
一个全新的文件,Git 将文件 复制到 其暂存区,作为一个新文件。
在所有这些情况下,暂存区中的所有现有文件都保留在那里。您的下一个 git commit
需要 全部 Git 暂存区中的文件,并从中制作快照。
一个具体的例子
假设你有一个现有的存储库,其中主要的 b运行ch(不管它的名字是什么:GitHub 现在鼓励人们使用 main
而旧的存储库倾向于使用 master
) 在其最近的提交中有十个文件。你 git clone
把这个存储库放到你的笔记本电脑上,所以你的笔记本电脑 Git 软件(“你的 Git”)检查最后一次提交,将十个文件提取到 Git 的暂存中区域和你的工作树。
您现在更改工作树中十个文件中的 五个,但是 运行 git add
仅 一个[=198] =] 五个更新的文件。这意味着您的 Git 的暂存区中有十个文件:九个文件与 当前提交 中的一个匹配,一个与您的 [=127= 中的更新文件匹配]工作树。四个暂存区文件不同于对应的四个工作树文件;其余六个暂存区文件与其对应的工作树匹配。
如果您现在 运行 git commit -m haaaaaands
,您将获得包含十个文件的新提交 与它们现在出现在暂存区中的完全一样 。您的工作树中仍然有所有更新的工作树文件,但是暂存区副本仍然与先前提交的副本匹配,因此新提交的副本与旧提交的副本匹配,除了您 运行 git add
.
您刚刚进行的新提交 成为 当前 提交,这是您笔记本电脑存储库中当前的最新提交b运行ch。您现在可以使用 git push
将此 commit 发送到 GitHub 存储库;如果你最终这样做了,他们收到的提交将逐位匹配存储在笔记本电脑存储库中的 Git 提交。它将具有 9 个文件匹配一个文件不匹配的情况;他们获得的提交将以先前的提交作为其父提交;等等。
关于 git status
的一些知识
首先,git status
会告诉您有关 当前 b运行ch 的信息。它会说类似 on branch main
的内容。这是你的 Git 告诉你你的笔记本电脑存储库有 main
作为 当前 b运行ch。您的 Git 也可能告诉您您“领先” and/or “落后”其他名称,例如 origin/main
:这使用 完全存储在本地的信息 ,在你的笔记本电脑上。此信息可能已过时,具体取决于其他 Git 存储库在 GitHub 上或其他任何地方的活跃程度。
接下来,如果您不在冲突合并的中间——如果您在,剩下的会变得更复杂——git status
命令 运行s two 比较:
首先,它将当前提交中的文件与暂存区中的文件进行比较。其中一些文件通常会完全匹配,因为自从它们从某个提交中提取后您没有对它们进行任何操作。对于那些文件,您的 Git 什么也没说。
暂存区中的其他文件不会匹配您当前的提交,因为例如您运行
git add
在它们上面。在这种情况下,您的 Git 会说这些文件 暂存用于提交 。这只是意味着暂存区副本在某些方面不同于当前提交的副本。请注意,暂存区中的一些文件可能是新的。也就是说,这些文件根本不存在于 current 提交中。对于这些文件,Git 会说这些是“新文件”。
已列出文件“暂存以供提交”,或未找到任何要列出的文件,您的 Git 现在继续将暂存区中的文件与工作区中的文件进行比较树。和以前一样,一些文件可能匹配。其他文件可能不同 — 甚至您的工作树中的一些文件在暂存区中根本没有对应文件:和以前一样是新文件。
不过这一次,您的 Git 只会告诉您有关 已更改的 个文件,并表示此类文件 未暂存提交 。它确实也收集了每个 new 文件的列表,但将它们推迟到下一部分。
列出所有“未准备提交”的文件后,您的 Git 继续告诉您 未跟踪的文件 。这些是您的工作树中 不在 Git 暂存区中的任何文件。换句话说,这些是“新”文件。
关于这些的奇怪之处在于它们是如何分离出来的,作为一个单独的类别进入“未跟踪”。这样做的原因是 Git 作者 期望 大量 的未跟踪文件 不应该此处报道。 Git 特别适用于创建“目标文件”和其他“构建工件”的编译器,虽然它们可能很重要,但不应添加到提交中并因此永远保存。1
就此而言,Git 通过 .gitignore
和其他排除文件提供了排除功能。在这里,您列出 Git 应该 关闭 ____ up 的文件。它应该而不是抱怨这些未跟踪的文件未被跟踪。此外,当这些文件 未被跟踪时,您可以使用 git add
操作,例如 git add .
,添加 all 未跟踪的文件...除了标记为“忽略”的文件。
.gitignore
的误导是它不会忽略 任何 跟踪 的文件。这里的tracked这个词是根据untracked的定义对立定义的。 未跟踪 文件是存在于您的工作树中但不在Git 的索引中的文件。 tracked 文件是 Git 索引中的文件,无论它是否存在于 Git 索引中。永远不会忽略跟踪的文件。
.gitignore
文件的良好维护使 Git 使用起来更加愉快:git status
告诉你只有 有用的东西; git add .
仅添加 正确的 项。
1这样做的原因是构建工件——至少,理想情况下——完全可以从原始来源复制。我们只想保存 originals,而不是派生的工作产品。这至少可以节省大量的 space 以及以后的时间和人工工作。注意,这里有很多“理想”和“潜力”。这些事情并不总是按计划进行,有时保存所有内容实际上是合理的。 Git 在这方面不是很好,所以您可能不想为此目的使用 Git。
“所有文件始终提交”的可能来源
如果你 运行 git add .
,你是在告诉 Git:扫描我当前的工作目录,找到所有更新的文件和所有新文件以及任何删除的文件,并在每个副本上使用 git add
来更新您的临时区域副本 。此处唯一的例外是 .gitignore
中列出的文件或其他尚未跟踪的排除文件。
如果您 运行 git add *
,行为在某种程度上取决于您的命令行解释器:Unix 风格的 CLI(例如 bash 或 zsh)具有 shell 扩展 *
,而 MS-DOS 风格的 CLI(例如 CMD.EXE)将文字星号 *
传递给 Git,这然后扩展 *
。我不会在这里详细讨论 all 差异的细节,但这往往会大量添加很多或所有文件,具体取决于许多细节。
如果你 运行 git add -u
,你告诉 Git 找到 更新的 文件并添加它们。
您可以有一个预提交挂钩。 Git 中的挂钩相当复杂,但某些软件安装程序不仅会为您安装 Git,还会设置某种自动创建挂钩的功能。 (这是一种重新初始化 Git 存储库 可以 产生影响的设置,尽管要这样做,安装程序必须将这些挂钩放入 Git “模板”,似乎很少使用。)预提交挂钩 可以 ,取决于您 运行 git commit
, 运行 git add
给你,即使你不想要。
如果你 运行 git commit -a
,你实际上是在告诉 Git 到 运行:
git add -u
git commit
这里有一个与预提交挂钩的交互,所以两个命令的顺序并不完全相同,但这可能是您问题的根源。
我已经通过对大文件使用 Git lfs 解决了这个问题。由于我使用的是 RStudio 服务器,我要求管理员安装 Git lfs 然后我执行这些
git lfs install
git lfs track "*.h5ad, *.h5Seurat"
git add .gitattributes
git lfs migrate info
git lfs migrate info --everything
git lfs migrate import --everything --a #override changes in your working copy?
[Y/n] Y
然后它将提交推送到 Github。请注意,*.h5ad 和 *h5Seurat 是我希望 Git lfs 处理的大文件扩展名。 我正在关注这个 link git lfs