visual studio 中的切换分支保留旧分支中的文件
switching branch in visual studio keeps the files form older branch
我创建了一个空的 repo 并克隆了主分支
然后我创建了一个空的 asp.net 核心 api 项目并在主分支中检查了它
然后我从主分支创建了新分支(服务)并在解决方案中添加了另一个项目(class 库项目)并将其命名为“服务”
这会创建一个名为“services”的文件夹
然后我上演它,提交上演并将其推送到“服务”分支
现在,当我检查主分支时,我希望“服务”文件夹不存在于我的文件系统中。但它仍然存在。
我是不是做错了什么,或者这就是它的工作原理?
Git 不“做”文件夹。 Git 只理解 文件.
文件在 Git 中的名称类似于 path/to/file.ext
。那不是一个名为 path
的文件夹,其中包含一个名为 to
的文件夹,其中包含一个名为 file.ext
的文件:它是一个名称为 path/to/file.ext
的文件,带有正斜杠(即使您的 OS 使用倒序,如 path\to\file.ext
).
您的OS,但是,无法处理这个。因此,Git 通过在需要时 在文件系统中创建 文件夹来容纳您的 OS,以保存名称中包含斜线的文件。如果你也创建这样的文件夹:
mkdir path path/to
然后在这些文件夹中创建文件,git add
它们:
echo new stuff > path/to/file.ext
git add path/to/file.ext
Git 理解您的意思是向 Git 添加一个名称中包含斜杠的文件,并且这样做了。它不会关注 文件夹 ——它不会添加 path/
或 path/to/
,只是最后的 path/to/file.ext
——但是它知道你的 OS 没有它们就无法工作,所以它容纳了它们。
当您随后切换回其他提交时,Git 有时会清除不需要的文件夹。在 Git 可以执行此操作之前需要几个条件,其中之一是文件夹为空 在 Git 删除任何与提交一起使用的文件正在 远离 并安装任何与您正在移动的提交一起使用的文件 到 。 (见下面的边栏。)
如果 Git 没有自行删除该文件夹,并且 git clean -df
也没有删除它,则该文件夹是 non-empty:它包含一些不是' 在 Git 中,或者与您切换到的提交一起使用。请注意,这些文件可能是隐藏的:始终使用“显示所有文件,包括隐藏的文件”来查看文件夹的内容。 小心 git clean
! 请参阅下面的侧边栏。
边栏(长且可选):提交保留快照
每个 Git 提交包含两件事:
它有一些元数据,或者关于提交本身的信息,包括提交人的姓名和电子邮件地址,一些 date-and-time 邮票,日志消息,等等。我们将在这里忽略它,尽管元数据的一部分对于 Git 自己的内部操作绝对至关重要:没有它,存储库中就不会有历史记录。
除了元数据之外,每个提交都充当 Git 知道的所有文件的 快照 在你(或任何人)做出承诺的时候。此快照很像每个文件的 tarball 或 WinRar 存档。然而,在这个快照中的文件是一种特殊的、压缩的、read-only、Git-only格式,其中内容是de-duplicated.
这意味着如果你有一百万个提交,每个提交都有一个 million-byte 文件,但是所有 100 万个文件 匹配 ,实际上只有 一个million-byte个文件。每个快照都在一遍又一遍地使用 相同的 文件。只有当您 更改并且 git add
文件时,您才会获得一个新的和不同的快照(对于接下来的一百万次提交,它可以是 re-used,如果没有再次更改)。
(虽然不会立即发生,Git 最终会生成“super-compresses”个文件,如果可以的话,这样如果两个 million-byte 副本可以相互压缩,其中一个最终可能会缩小到几十个字节。这取决于 delta encoding,它对某些文本格式非常有效,但几乎不适用 pre-compressed 二进制数据,如 JPG 图像.)
快照inside 每次提交完全、完全、100% read-only。 (事实上,元数据也是如此。)这就是 为什么 不同的提交可以在它们的快照中共享文件:因为 none 的提交被允许 更改其中任何一个,所有提交都允许共享其中任何一个。但事实上,这些文件仅 可读 ,即使如此,也只能由 Git 本身 读取,这意味着您实际上无法执行任何操作使用 这些文件。
因此,你不需要。 您永远不会使用 在 提交中的文件。相反,您使用副本 的文件,从提交 复制到工作区。 换句话说,您不要处理 在 Git 中的文件,你要处理 不在 Git 中的文件。 在Git的文件不是你用的,你用的也不在Git.
只有当您 运行 git add
和 git commit
时,Git 才会创建 new 快照。新快照包括:
- 之前提取的所有快照文件,
- 减去任何你
git rm
-ed,
- 加上任何你
git add
-ed
Git 保留了一种 运行ning 提议的下一次提交 ,最初由 git checkout
或 git switch
填写,当您将 切换为 某些提交。当你 git add
一些 existing 文件时,Git 通过启动 current 副本并放入来调整提议的下一次提交new 副本:Git 压缩工作树副本——Git 中 not 的副本——压缩到内部, read-only 表单, 检查重复项 ,如果有重复项,则立即使用。如果没有,Git 准备压缩文件用于提交并使用它。无论哪种情况,建议的下一次提交现在都已更新。
当你 git rm
一个文件时,Git 删除工作树副本(你可以看到和使用的那个)和 proposed-next-commit 复制。建议的下一次提交现已更新。
当您 git add
一个全新的文件时,Git 压缩工作树副本,检查它是否重复(对于 git add
-ing 现有文件),然后将副本或准备好的文件添加到建议的下一次提交中。建议的下一次提交现已更新。
任何时候你切换提交,Git:
检查当前“建议的下一次提交”:其中的所有文件是否与当前提交完全相同?如果是这样,它们可以安全丢弃。如果不是,他们就不是。
检查您要切换到的提交。它现在是否具有与当前提交中完全相同的文件?如果是这样,Git 不必 fiddle 与那些,在提议的下一次提交 或 你的工作树中,所以它不会打扰。如果不是,Git 将不得不在提议的下一次提交中添加或删除一些文件。它要接触到这里的那些可以安全丢弃吗?
所有这些检查导致 Checkout another branch when there are uncommitted changes on the current branch 的复杂答案。不过,我们可以在这里使用两个非常重要的 short-cut 概念:
如果我们要求 Git 从提交 a123456
“切换”到提交 a123456
——也就是说,如果 [=130= current 提交的哈希 ID 与我们要切换到的 new 提交的哈希 ID 完全匹配——然后我们根本没有切换提交。这意味着根本不需要更新 提议的下一次提交 ,这反过来意味着 branch-switching 是允许的。因此,如果我们在此过程中不更改 commit hash IDs,我们总是可以创建并切换到 new b运行ch。对于简单的情况总是如此:
git switch -c new-branch
或
git checkout -b new-branch
创建并切换到新的 b运行ch 而无需更改提交。所以这意味着如果我们开始工作而忘记先创建一个 new b运行ch,我们就在 运行 git commit
之前创建一个然后我们很好。
如果所有文件都是“干净的”——例如,如果我们自上次进行新提交以来没有进行任何更改,那么 git status
表示 nothing to commit, working tree clean
——然后我们可以安全地切换 b运行ches,不管我们要从哪个提交移动到哪个提交。
但是,对于第二个要点有一个非常重要的警告。 Git 将从我们的工作树和它的索引 / staging-area 中 删除 ——即从提议的下一次提交中——所有由于当前提交 而存在的文件,并且将在我们的工作树中安装与 other 提交一起使用的所有文件。这是正确的即使一些文件被.gitignore
标记为“忽略”:实际上在暂存区中的文件是根据定义,“跟踪”,因此受 removal-and-replacement 约束(前提是它是“干净的”,如 git status
中所说 nothing to commit, working tree clean
)。
所以,简而言之:tracked 文件是 提议的下一次提交 中的文件,即 Git 中的文件index aka 暂存区。这些将是 removed-and-replaced 切换提交时,如果目标提交 - 您正在切换 到 的那个 - 缺少 文件,它们将被简单地删除。
这给我们留下了未跟踪文件的概念,这些文件的定义很简单:未跟踪文件是是 在你的工作树中,但是 不在 在 Git 的索引 / staging-area 现在 . 为什么 现在不存在并不重要。它可能不存在,因为它从未存在过:从来没有任何提交。它可能不存在,因为它不在您切换到的提交中(例如,也许提交 b789abc
有一个文件 read.me
但较早的提交 a123456
没有,并且您已经切换到较早的提交,因此该文件不在提交中,但是无论如何您都将副本保存到您的工作树中)。或者它可能不存在,因为你运行git rm --cached
。无论如何,文件 是 在您的工作树中,而 不是 在提议的下一次提交中。
鉴于该文件不在建议的下一次提交(暂存区)中,它很可能根本不在 Git 中,在 any 中犯罪。它可能在某个提交中;也许这是上面列出的奇怪案例之一。但是通常像 main.pyc
这样的文件(一个 Python byte-compiled 文件)不在 any 提交中,因为你告诉 Git 永远不要通过在 .gitignore
中列出它来添加此 ,并且您从未添加过它,因此从未提交过它。 Python 然后去创建它,所以它就在你的工作树中。如果它是一个 Python *.pyc
文件,那么继续删除它是非常安全的。
但每个 未跟踪文件并非如此。有时一些未跟踪的文件是数小时甚至数天工作的产物,而您只是还没有 运行 git add
和 git commit
。它很珍贵,但它是唯一的副本……它就在你的工作树中,Git 可能会覆盖文件。
因为它不在任何提交中,所以这个未跟踪的文件目前没有危险。从一个提交切换到另一个提交只会 remove-and-replace tracked 文件,并且存储库中的 no commit 将此文件作为跟踪文件,所以这个文件将保持不变:你的宝贵工作是绝对安全的,即使它位于这个相当危险的位置,在 Git 工作树中。它的 untracked-ness 和 un-committed-ness 几乎是一种无形的盾牌,保护着文件。 但是有一个Git命令可以穿透这个盾牌,那就是git clean
。 git clean
命令的任务 是 删除未跟踪的文件 .
因此您应该非常小心 git clean
。 它会删除未跟踪的文件,根据定义,这些未跟踪的文件不在 提议下一次提交 并且很有可能他们甚至不在 any 提交中。这意味着如果您删除它们,Git 无法帮助您取回这些文件。如果它们是 computer-generated 文件,就像我们的 main.pyc
示例,那没什么大不了的,但是如果它们需要数小时或数天的工作才能 re-create,那么, 是 一件大事。所以要小心 git clean
!
我创建了一个空的 repo 并克隆了主分支
然后我创建了一个空的 asp.net 核心 api 项目并在主分支中检查了它
然后我从主分支创建了新分支(服务)并在解决方案中添加了另一个项目(class 库项目)并将其命名为“服务”
这会创建一个名为“services”的文件夹
然后我上演它,提交上演并将其推送到“服务”分支
现在,当我检查主分支时,我希望“服务”文件夹不存在于我的文件系统中。但它仍然存在。
我是不是做错了什么,或者这就是它的工作原理?
Git 不“做”文件夹。 Git 只理解 文件.
文件在 Git 中的名称类似于 path/to/file.ext
。那不是一个名为 path
的文件夹,其中包含一个名为 to
的文件夹,其中包含一个名为 file.ext
的文件:它是一个名称为 path/to/file.ext
的文件,带有正斜杠(即使您的 OS 使用倒序,如 path\to\file.ext
).
您的OS,但是,无法处理这个。因此,Git 通过在需要时 在文件系统中创建 文件夹来容纳您的 OS,以保存名称中包含斜线的文件。如果你也创建这样的文件夹:
mkdir path path/to
然后在这些文件夹中创建文件,git add
它们:
echo new stuff > path/to/file.ext
git add path/to/file.ext
Git 理解您的意思是向 Git 添加一个名称中包含斜杠的文件,并且这样做了。它不会关注 文件夹 ——它不会添加 path/
或 path/to/
,只是最后的 path/to/file.ext
——但是它知道你的 OS 没有它们就无法工作,所以它容纳了它们。
当您随后切换回其他提交时,Git 有时会清除不需要的文件夹。在 Git 可以执行此操作之前需要几个条件,其中之一是文件夹为空 在 Git 删除任何与提交一起使用的文件正在 远离 并安装任何与您正在移动的提交一起使用的文件 到 。 (见下面的边栏。)
如果 Git 没有自行删除该文件夹,并且 git clean -df
也没有删除它,则该文件夹是 non-empty:它包含一些不是' 在 Git 中,或者与您切换到的提交一起使用。请注意,这些文件可能是隐藏的:始终使用“显示所有文件,包括隐藏的文件”来查看文件夹的内容。 小心 git clean
! 请参阅下面的侧边栏。
边栏(长且可选):提交保留快照
每个 Git 提交包含两件事:
它有一些元数据,或者关于提交本身的信息,包括提交人的姓名和电子邮件地址,一些 date-and-time 邮票,日志消息,等等。我们将在这里忽略它,尽管元数据的一部分对于 Git 自己的内部操作绝对至关重要:没有它,存储库中就不会有历史记录。
除了元数据之外,每个提交都充当 Git 知道的所有文件的 快照 在你(或任何人)做出承诺的时候。此快照很像每个文件的 tarball 或 WinRar 存档。然而,在这个快照中的文件是一种特殊的、压缩的、read-only、Git-only格式,其中内容是de-duplicated.
这意味着如果你有一百万个提交,每个提交都有一个 million-byte 文件,但是所有 100 万个文件 匹配 ,实际上只有 一个million-byte个文件。每个快照都在一遍又一遍地使用 相同的 文件。只有当您 更改并且 git add
文件时,您才会获得一个新的和不同的快照(对于接下来的一百万次提交,它可以是 re-used,如果没有再次更改)。
(虽然不会立即发生,Git 最终会生成“super-compresses”个文件,如果可以的话,这样如果两个 million-byte 副本可以相互压缩,其中一个最终可能会缩小到几十个字节。这取决于 delta encoding,它对某些文本格式非常有效,但几乎不适用 pre-compressed 二进制数据,如 JPG 图像.)
快照inside 每次提交完全、完全、100% read-only。 (事实上,元数据也是如此。)这就是 为什么 不同的提交可以在它们的快照中共享文件:因为 none 的提交被允许 更改其中任何一个,所有提交都允许共享其中任何一个。但事实上,这些文件仅 可读 ,即使如此,也只能由 Git 本身 读取,这意味着您实际上无法执行任何操作使用 这些文件。
因此,你不需要。 您永远不会使用 在 提交中的文件。相反,您使用副本 的文件,从提交 复制到工作区。 换句话说,您不要处理 在 Git 中的文件,你要处理 不在 Git 中的文件。 在Git的文件不是你用的,你用的也不在Git.
只有当您 运行 git add
和 git commit
时,Git 才会创建 new 快照。新快照包括:
- 之前提取的所有快照文件,
- 减去任何你
git rm
-ed, - 加上任何你
git add
-ed
Git 保留了一种 运行ning 提议的下一次提交 ,最初由 git checkout
或 git switch
填写,当您将 切换为 某些提交。当你 git add
一些 existing 文件时,Git 通过启动 current 副本并放入来调整提议的下一次提交new 副本:Git 压缩工作树副本——Git 中 not 的副本——压缩到内部, read-only 表单, 检查重复项 ,如果有重复项,则立即使用。如果没有,Git 准备压缩文件用于提交并使用它。无论哪种情况,建议的下一次提交现在都已更新。
当你 git rm
一个文件时,Git 删除工作树副本(你可以看到和使用的那个)和 proposed-next-commit 复制。建议的下一次提交现已更新。
当您 git add
一个全新的文件时,Git 压缩工作树副本,检查它是否重复(对于 git add
-ing 现有文件),然后将副本或准备好的文件添加到建议的下一次提交中。建议的下一次提交现已更新。
任何时候你切换提交,Git:
检查当前“建议的下一次提交”:其中的所有文件是否与当前提交完全相同?如果是这样,它们可以安全丢弃。如果不是,他们就不是。
检查您要切换到的提交。它现在是否具有与当前提交中完全相同的文件?如果是这样,Git 不必 fiddle 与那些,在提议的下一次提交 或 你的工作树中,所以它不会打扰。如果不是,Git 将不得不在提议的下一次提交中添加或删除一些文件。它要接触到这里的那些可以安全丢弃吗?
所有这些检查导致 Checkout another branch when there are uncommitted changes on the current branch 的复杂答案。不过,我们可以在这里使用两个非常重要的 short-cut 概念:
如果我们要求 Git 从提交
a123456
“切换”到提交a123456
——也就是说,如果 [=130= current 提交的哈希 ID 与我们要切换到的 new 提交的哈希 ID 完全匹配——然后我们根本没有切换提交。这意味着根本不需要更新 提议的下一次提交 ,这反过来意味着 branch-switching 是允许的。因此,如果我们在此过程中不更改 commit hash IDs,我们总是可以创建并切换到 new b运行ch。对于简单的情况总是如此:git switch -c new-branch
或
git checkout -b new-branch
创建并切换到新的 b运行ch 而无需更改提交。所以这意味着如果我们开始工作而忘记先创建一个 new b运行ch,我们就在 运行
git commit
之前创建一个然后我们很好。如果所有文件都是“干净的”——例如,如果我们自上次进行新提交以来没有进行任何更改,那么
git status
表示nothing to commit, working tree clean
——然后我们可以安全地切换 b运行ches,不管我们要从哪个提交移动到哪个提交。
但是,对于第二个要点有一个非常重要的警告。 Git 将从我们的工作树和它的索引 / staging-area 中 删除 ——即从提议的下一次提交中——所有由于当前提交 而存在的文件,并且将在我们的工作树中安装与 other 提交一起使用的所有文件。这是正确的即使一些文件被.gitignore
标记为“忽略”:实际上在暂存区中的文件是根据定义,“跟踪”,因此受 removal-and-replacement 约束(前提是它是“干净的”,如 git status
中所说 nothing to commit, working tree clean
)。
所以,简而言之:tracked 文件是 提议的下一次提交 中的文件,即 Git 中的文件index aka 暂存区。这些将是 removed-and-replaced 切换提交时,如果目标提交 - 您正在切换 到 的那个 - 缺少 文件,它们将被简单地删除。
这给我们留下了未跟踪文件的概念,这些文件的定义很简单:未跟踪文件是是 在你的工作树中,但是 不在 在 Git 的索引 / staging-area 现在 . 为什么 现在不存在并不重要。它可能不存在,因为它从未存在过:从来没有任何提交。它可能不存在,因为它不在您切换到的提交中(例如,也许提交 b789abc
有一个文件 read.me
但较早的提交 a123456
没有,并且您已经切换到较早的提交,因此该文件不在提交中,但是无论如何您都将副本保存到您的工作树中)。或者它可能不存在,因为你运行git rm --cached
。无论如何,文件 是 在您的工作树中,而 不是 在提议的下一次提交中。
鉴于该文件不在建议的下一次提交(暂存区)中,它很可能根本不在 Git 中,在 any 中犯罪。它可能在某个提交中;也许这是上面列出的奇怪案例之一。但是通常像 main.pyc
这样的文件(一个 Python byte-compiled 文件)不在 any 提交中,因为你告诉 Git 永远不要通过在 .gitignore
中列出它来添加此 ,并且您从未添加过它,因此从未提交过它。 Python 然后去创建它,所以它就在你的工作树中。如果它是一个 Python *.pyc
文件,那么继续删除它是非常安全的。
但每个 未跟踪文件并非如此。有时一些未跟踪的文件是数小时甚至数天工作的产物,而您只是还没有 运行 git add
和 git commit
。它很珍贵,但它是唯一的副本……它就在你的工作树中,Git 可能会覆盖文件。
因为它不在任何提交中,所以这个未跟踪的文件目前没有危险。从一个提交切换到另一个提交只会 remove-and-replace tracked 文件,并且存储库中的 no commit 将此文件作为跟踪文件,所以这个文件将保持不变:你的宝贵工作是绝对安全的,即使它位于这个相当危险的位置,在 Git 工作树中。它的 untracked-ness 和 un-committed-ness 几乎是一种无形的盾牌,保护着文件。 但是有一个Git命令可以穿透这个盾牌,那就是git clean
。 git clean
命令的任务 是 删除未跟踪的文件 .
因此您应该非常小心 git clean
。 它会删除未跟踪的文件,根据定义,这些未跟踪的文件不在 提议下一次提交 并且很有可能他们甚至不在 any 提交中。这意味着如果您删除它们,Git 无法帮助您取回这些文件。如果它们是 computer-generated 文件,就像我们的 main.pyc
示例,那没什么大不了的,但是如果它们需要数小时或数天的工作才能 re-create,那么, 是 一件大事。所以要小心 git clean
!