git - 为什么提交一个文件,但所有文件都在 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 存储库,无论它在哪里。
如果 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
创建一个新的、完全空的存储库时,没有提交,因此还没有分支。因此,您进行的下一次提交是有史以来的第一次提交。这个提交有点特别:它是一个根提交,没有历史。它包含你告诉 Git 让它包含的任何文件,使用git add
.
但是,在此之后,您将拥有一个包含现有提交的现有 Git 存储库。这包括您使用git clone
将一些现有存储库(例如,从 GitHub)复制到您自己的机器(例如,您的笔记本电脑)上的新 Git 存储库的情况。您将告诉 Git检查某个特定的提交(通常是某个分支名称的提示提交),这意味着 Git 将使用该提交中的所有文件填充其暂存区域和您的工作树。
随后,您将编辑一些文件,甚至可能创建一些新文件。然后,您git add
在这些文件中的一个或多个上运行。如果你正在git add
处理一个已经存在于 Git 暂存区的文件,Git 会从它的暂存区扔掉旧的副本,并用你的工作树制作的新副本覆盖暂存区的副本。或者,如果你git add
是一个全新的文件,Git 会将文件复制到它的暂存区,作为一个新文件。
在所有这些情况下,暂存区域中的所有现有文件都保留在那里。 接下来git commit
获取Git 暂存区域中的所有文件,并从中制作快照。
一个具体的例子
假设您有一个现有的存储库,其中主分支(无论它的名称是什么:GitHub 现在鼓励人们使用main
,而旧的存储库倾向于使用master
)在其最近的提交中有十个文件。您git clone
将此存储库添加到您的笔记本电脑,因此您的笔记本电脑 Git 软件(“您的 Git”)会检查最后一次提交,将十个文件提取到 Git 的暂存区和您的工作树中。
您现在更改了工作树中十个文件中的五个git add
,但只在五个更新文件中的一个上运行。这意味着您的 Git 暂存区中有十个文件:九个文件与当前提交中的一个匹配,一个与工作树中的更新文件匹配。四个暂存区文件不同于它们的四个工作树对应文件;其余六个暂存区文件与它们的工作树对应文件匹配。
如果您现在运行git commit -m haaaaaands
,您将获得一个包含十个文件的新提交,这些文件与它们现在出现在暂存区域中的完全相同。您的工作树中仍然拥有所有更新的工作树文件,但暂存区副本仍然与先前提交的副本匹配,因此新提交的副本与旧提交的副本匹配,除了您运行的一个文件git add
。
您刚刚进行的新提交成为当前提交,现在是当前分支上笔记本电脑存储库中的最新提交。您现在可以使用git push
将此提交发送到 GitHub 存储库;如果并且当您最终这样做时,他们收到的提交将逐位匹配您的 Git 存储在笔记本电脑存储库中的提交。它将有 9 个文件匹配一个文件不匹配的情况;他们获得的提交将以先前的提交作为其父提交;等等。
需要了解的事情git status
首先,git status
告诉您有关当前分支的信息。它会说类似on branch main
. 这是您的 Git 告诉您您的笔记本电脑存储库已main
作为当前分支。您的 Git 也可能会告诉您您“领先”和/或“落后”其他名称,例如origin/main
:这使用完全本地存储在笔记本电脑上的信息。此信息可能已过时,具体取决于其他 Git 存储库在 GitHub 上或其他任何地方的活跃程度。
接下来,如果您没有处于冲突合并的中间——如果是,其余的会变得更加复杂——该git status
命令运行两个比较:
首先,它将当前提交中的文件与暂存区中的文件进行比较。其中一些文件通常会完全匹配,因为自从它们从某个提交中提取后,您没有对它们做任何事情。对于这些文件,你的 Git 什么也没说。
暂存区域中的其他文件将与您当前的提交不
git add
匹配,因为例如您在它们上运行。在这种情况下,你的 Git 会说这些文件是为提交暂存的。这仅仅意味着暂存区副本在某种程度上与当前提交的副本不同。请注意,暂存区域中的某些文件可能是新文件。也就是说,这些文件在当前提交中根本不存在。对于这些文件,Git 会说这些是“新文件”。
列出了“暂存待提交”的文件,或者没有找到任何要列出的文件,您的 Git 现在继续将暂存区域中的文件与工作树中的文件进行比较。和以前一样,某些文件可能匹配。其他文件可能会有所不同,甚至工作树中的某些文件在暂存区域中根本没有对应文件:与以前一样是新文件。
不过,这一次,您的 Git 只会告诉您有关已更改文件的信息,并表示此类文件不会暂存以进行提交。它确实也收集了每个新文件的列表,但将它们推迟到下一部分。
列出所有“未暂存以供提交”的文件后,您的 Git 会继续告诉您有关未跟踪文件的信息。这些是工作树中不在Git 暂存区中的任何文件。换句话说,这些是“新”文件。
这些的奇怪之处在于它们是如何被分离出来的,作为一个单独的类别进入“未跟踪”。这样做的原因是 Git 作者希望这里不应该报告大量未跟踪的文件。特别是 Git 是为与创建“目标文件”和其他“构建工件”的编译器一起工作而构建的,尽管它们可能很重要,但不应添加到提交中并因此永久保存。1
在这个程度上,Git 有一个排除工具,via.gitignore
和其他排除文件。在这里,您列出了 Git 应该关闭的文件。它不应该抱怨这些未跟踪的文件是未跟踪的。此外,当这些文件未被跟踪时,您可以使用 en-massegit add
操作,例如git add .
,添加所有未跟踪的文件......除了那些标记为“忽略”的文件。
令人误解的.gitignore
是它不会忽略任何被跟踪的文件。这里的tracked一词是根据untracked的定义的对立来定义的。未跟踪文件是存在于工作树中但不存在于 Git 索引中的文件。跟踪文件是 Git 索引中的文件,无论它是否存在于 Git 索引中。跟踪的文件永远不会被忽略。
良好的文件维护.gitignore
使 Git 使用起来更加愉快:只git status
告诉你有用的东西;只添加正确的东西。git add .
1这样做的原因是,构建工件(至少在理想情况下)完全可以从原始来源重现。我们只想保存原件,而不是派生的工作产品。这至少可以节省大量的空间和时间以及以后的人工工作。请注意,这里有很多“理想”和“潜力”。这些事情并不总是按计划进行,有时保存一切实际上是合理的。不过,Git 在这方面并不是那么出色,因此您可能不想为此目的使用Git 。
“所有文件始终提交”的可能来源
如果你运行git add .
,你是在告诉 Git:扫描我当前的工作目录,找到所有更新的文件和所有新的文件和任何删除的文件,并git add
在每个文件上使用来更新你的暂存区副本。.gitignore
此处唯一的例外是未跟踪的文件或其他排除文件中列出的文件。
如果您运行git add *
,则行为在某种程度上取决于您的命令行解释器:Unix 风格的 CLI(如 bash 或 zsh)让shell扩展*
,而 MS-DOS 风格的 CLI(如 CMD.EXE)将文字星号传递*
给 Git , 然后扩展*
. 我不会在这里详细介绍差异的所有细节,但这往往会根据许多细节进行大量或全部文件的整体添加。
如果运行git add -u
,则告诉 Git 查找更新的文件并添加它们。
你可以有一个预提交钩子。Git 中的钩子相当复杂,但一些软件安装程序不仅会为您安装 Git,还会设置某种自动钩子创建。(这是一种重新初始化 Git 存储库可能会产生影响的设置,尽管要这样做,安装程序必须将这些挂钩放入 Git“模板”中,这似乎很少使用。)根据您的运行方式,预提交挂钩可以为您运行,即使您不希望它运行。git commit
git add
如果你运行git commit -a
,你实际上是在告诉 Git 运行:
git add -u
git commit
这里有一个与预提交挂钩的交互,因此两个命令序列并不完全相同,但这可能是您问题的根源。
推荐阅读
- r - 如何在R中减去两个数字?
- python - 如果我想在另一台没有安装 python 的机器上运行包含模块的 python 代码,我可以这样做吗?
- c# -
- python - Pandas infer_objects() 不会将字符串列转换为数字
- python - 客户端/服务器 Pygame 执行挂起
- postgresql - Postgres 11.7 中数字的 CREATE TYPE 和转换问题
- debugging - Flutter 调试/Gradle 构建错误 ':app:compileFlutterBuildDebug'
- python - 将数据帧的字典转换为单个数据帧
- mongoose - 如何在 Mongoose 模式中为同一属性使用多种类型?
- php - NEWID 函数导致 MYSQL 中准备好的语句出错