国外社交网站设计欣赏,网页设计html代码大全继承关系,门户网站案例分析,宜阳县网站建设在我撰写的 Git DevOps 文章 (msdn.com/magazine/mt767697) 中#xff0c;我介绍了 Git 版本控制系统 (VCS) 与可能已经很熟悉的集中式 VCS 的区别。然后#xff0c;我演示了如何在 Visual Studio 中使用 Git 工具完成一些 Git 任务。在本文中#xff0c;我将汇总 Git 在新发…在我撰写的 Git DevOps 文章 (msdn.com/magazine/mt767697) 中我介绍了 Git 版本控制系统 (VCS) 与可能已经很熟悉的集中式 VCS 的区别。然后我演示了如何在 Visual Studio 中使用 Git 工具完成一些 Git 任务。在本文中我将汇总 Git 在新发布的 Visual Studio 2017 IDE 中的运作方式的相关变化并介绍 Git 存储库在文件系统中的实现方式。之后我将探究数据存储的拓扑和各种存储对象的结构和内容。最后我将对 Git 分支进行低级别解释以阐明我的观点即希望大家能够理解我将在近期发表的文章中介绍的更高级 Git 操作。 注意 在本文中我没有使用服务器或远程方案。我探究的是纯本地方案可以在安装了 Visual Studio 2017 和 Git for Windows (G4W) 的任何一台 Windows 计算机已连接或未连接 Internet/网络连接上进行操作。本文介绍了 Git 内部源代码。阅读本文的前提是熟悉 Visual Studio Git 工具以及 Git 基本操作和概念。 Visual Studio、Git 和你 Git 不仅是指包含版本控制数据存储的存储库也是指处理管理命令的引擎 底层命令执行低级别操作高层命令以类似于宏的方式捆绑底层命令从而宏观调用简化操作。掌握 Git 后你会发现一些任务需要用到这些命令我将在本文中使用其中一些命令并且需要使用命令行接口 (CLI) 来调用这些命令。遗憾的是Visual Studio 2017 不再安装 Git CLI因为它使用的新 Git 引擎 MinGit 并不提供 Git CLI。与 G4W 2.10 一同发布的 MinGit“最简 Git”是可移植的简化功能集 API专为需要与 Git 存储库进行交互的 Windows 应用程序而设计。G4W 乃至 MinGit 都是官方 Git 开放源代码项目的分支。也就是说它们都继承了官方 Git 修补程序和更新程序只要已发布并确保 Visual Studio 可以执行同样的操作。 若要访问 Git CLI并继续和我一起操作建议安装完整的 G4W 程序包。虽然有其他 Git CLI/GUI 工具选项但 G4W作为 MinGit 的官方父级引擎是明智之选特别是因为它与 MinGit 共享配置文件。若要获取最新的 G4W 安装程序请访问官方网站来源 (git-scm.com) 的“下载”部分。运行安装程序并选中“Git Bash Here”复选框创建 Git 命令提示符窗口和“Git GUI Here”复选框创建 Git GUI 窗口。这样一来便可以在 Windows 资源管理器中轻松右键单击文件夹然后对当前文件夹选择这两个选项之一Git Bash 中的“Bash”是指 Bourne Again Shell在 G4W 的 Unix shell 中表示 Git CLI。下一步选择“通过 Windows 命令提示符使用 Git”这会将环境配置为可以在 Visual Studio 程序包管理器控制台 (Windows PowerShell) 或命令提示符窗口中轻松运行 Git 命令。 如果使用我在本文中建议的选项安装 G4W见图 1通信路径将会在与 Git 存储库通信时生效 Visual Studio 2017 使用 MinGit API而 PowerShell 和命令提示符会话则使用 G4W CLI这是与 Git 存储库通信的不同通信路径。虽然 MinGit 和 G4W 是不同的通信终结点但都派生自官方 Git 源代码并共享配置文件。请注意发出的高层命令会先被转换成底层命令然后再由 CLI 进行处理。重要的是了解 Git 专家通常会有时完全依靠向 CLI 发出裸机 Git 底层命令因为这样做是管理、查询和更新 Git 存储库的最直接方法也是最低级别方法。与低级别的底层命令相比Visual Studio IDE 公开的更高级别高层命令和 Git 操作也可以更新 Git 存储库但具体方式始终不太清楚特别是因为高层命令经常接受在调用时行为发生变化的选项。我得出的结论是熟悉 Git 底层命令对充分利用 Git 功能必不可少。正因为此我强烈建议同时安装 G4W 和 Visual Studio 2017。若要详细了解 Git 底层命令和高层命令请访问 git-scm.com/docs。 图 1MinGit API 和 Git for Windows 命令行接口的往来通信路径 低级别 Git Visual Studio 开发者在迁移到 Git 时很自然就会试图利用 VCS 的现有知识如 Team Foundation Server (TFS)。用于描述这两个系统中的操作的术语和概念如签出/签入代码合并、分支等的确存在重叠。不过如果因此假设类似词汇指代的基础操作也类似是十足错误和危险的想法。这是因为分散式 Git VCS 存储和跟踪文件的方式以及其实现熟悉的版本控制功能的方式是根本不同的。简单来说在迁移到 Git 时最佳做法可能是完全忘掉关于集中式 VCS 所掌握的一切知识然后重新开始学习。 在处理受 Git 源代码管理的 Visual Studio 项目时典型的编辑/分段处理/提交流程如下 根据需要在项目中添加、编辑和删除以下统称为“更改”文件。完成后先对部分或所有这些更改进行分段处理然后再将文件提交到存储库中。提交后这些更改就会变成存储库完整透明的修订记录的一部分。现在让我们来了解一下 Git 是如何在内部管理此流程的每一步的。 有向无环图在后台每次提交最终成为 Git 托管的有向无环图图论用语为“DAG”上的顶点节点。DAG 代表 Git 存储库每个顶点代表称为“提交对象”的数据元素见图 2。DAG 中的顶点与称为“边”的线相连按照惯例将 DAG 边绘制为箭头这样可以表示父/子关系头指向父顶点尾指向子顶点。原始顶点表示存储库的首次提交终端顶点没有子顶点。DAG 边表示所连每个顶点之间的确切父子关系。由于 Git 提交对象简称为“提交”表示为顶点因此 Git 可以利用 DAG 结构对所有提交之间的父子关系进行建模这样 Git 便能够生成从任意一次提交向后追溯到存储库初始提交的修订记录。此外与线性图不同的是DAG 支持分支一个父顶点有多个子顶点和合并一个子顶点有多个父顶点。每当提交对象生成一个新的子顶点便会生成 Git 分支每当多个提交对象合并成一个子顶点时便会发生合并。 图 2显示顶点、边、头、尾、原始顶点和终端顶点的有向无环图3 个分支A、B 和 C2 个分支事件在 A4 处1 个合并事件B3 和 A5 在 A6 处合并 我已经非常详尽地介绍了 DAG 及其相关术语因为此类知识是了解高级 Git 操作的先决条件掌握这些知识的具体方式往往为管理 Git DAG 上的顶点。此外DAG 有助于直观呈现 Git 存储库广泛用于教学资料、演示和 Git GUI 工具。 Git 对象概览到目前为止我只提到了 Git 提交对象。不过实际上Git 在存储库中存储以下四种不同类型的对象提交、树、blob 和标记。若要调查以上每种类型请启动 Visual Studio我使用的是 Visual Studio 2017但支持 Git 的旧版的运作方式也类似然后使用“文件 | 新建项目”新建一个控制台应用程序。命名项目选中“新建 Git 存储库”复选框然后单击“确定”。如果之前没有在 Visual Studio 中配置过 Git将会看到“Git 用户信息”对话框。如果看到请指定你的姓名和电子邮件地址每次提交时此类信息都会写入 Git 存储库。此外若要对计算机上的每个 Git 存储库使用此类信息请选中“设置全局 .gitconfig”复选框。 完成后打开“解决方案资源管理器”窗口见图 3 中的标记 1。可以看到文件旁边显示有淡蓝色锁形图标尽管我还没有进行过提交 此示例表明Visual Studio 有时可能会对存储库执行非预期操作。 若要确切了解 Visual Studio 执行的操作请查看当前分支的修订记录。 图 3新建的 Visual Studio 项目及其 Git 存储库修订记录报告 Git 将默认分支命名为“master”并使之成为当前分支。Visual Studio 在状态栏的右边缘显示当前分支的名称标记 2。当前分支表示 DAG 上将成为下一次提交的父级的提交对象稍后将会详细介绍分支。若要查看当前分支的提交修订记录请单击主分支标签标记 2然后选择菜单中的“查看修订记录”标记 3。 随即出现的“修订记录 - 主分支”窗口在多列中显示信息。左侧标记4是 DAG 上的两个顶点每个顶点均经过图形处理在 Git DAG 上表示一次提交。“ID”、“作者”、“日期”和“消息”列标记 5显示每次提交的详细信息。主分支的 HEAD 以深红色指针标记 6表示我将在本文快结束时全面讲解这其中的含义。此 HEAD 标记了当提交在 DAG 中添加了新顶点后下一个边箭头的头位置。 报告显示 Visual Studio 进行了两次提交每次提交都有自己的提交 ID标记 7。第一次最早提交由 ID a759f283 进行唯一标识第二次提交则由 bfeb0957 进行唯一标识。这些值截取自包含 40 个字符的完整十六进制安全哈希算法 1 (SHA-1)。SHA-1 是一种加密哈希函数旨在通过获取消息如提交数据并创建消息摘要即完整的 SHA-1 哈希值如提交 ID来检测是否有损坏。简单来说SHA-1 哈希算法的行为不仅类似于校验和还类似于 GUID因为有大约 1.46 x 1048 个唯一组合。与其他许多 Git 工具一样Visual Studio 仅显示完整值的前 8 个字符因为有 43 亿个惟一值足以在日常工作中避免冲突发生。若要查看完整的 SHA-1 值请将鼠标悬停在“修订记录报告”标记 8中的行之上。 虽然“查看修订记录报告”的消息列会指明每个提交的声明用途由提交者在提交过程中提供但毕竟只是注释而已。若要查看提交的实际更改请右键单击列表中的行然后选择“查看提交详细信息”见图 4。 图 4存储库前两次提交的提交详细信息 第一次提交标记 1包含两个更改.gitignore 和 .gitattributes我在上一篇文章中介绍过这些文件。 每个文件旁边的“[添加]”表明文件是被添加到存储库中。第二次提交标记 2不仅显示添加了 5 个文件还将父提交对象的 ID 显示为可单击链接。若要将完整的 SHA-1 值复制到剪贴板中只需单击“操作”菜单然后选择“复制提交 ID”即可。 在文件系统中实现 Git 存储库若要查看 Git 如何在存储库中存储这些文件请右键单击解决方案资源管理器中的解决方案而不是项目然后选择文件资源管理器中的“打开文件夹”。在解决方案的根目录下可以看到 .git 隐藏文件夹如果看不到 .git请单击文件资源管理器“视图”菜单中的“已隐藏项”。.git 文件夹是项目的 Git 存储库。它的 objects 文件夹定义了 DAG 所有 DAG 顶点以及所有顶点之间的全部父子关系都是通过文件进行编码这些文件表示存储库中从原始顶点开始的每次提交再次见图 2。.git 文件夹的 HEAD 文件和 refs 文件夹定义了分支。让我们来深入了解一下这些 .git 项。 探索 Git 对象 .git\objects 文件夹存储所有类型的 Git 对象提交对于提交、树对于文件夹、blob对于二进制文件和标记易记的提交对象别名。 提交对象现在是时候启动 Git CLI 了。可以使用常用的任意工具Git Bash、PowerShell 或命令窗口。我将使用 PowerShell。首先转到解决方案根目录的 .git\objects 文件夹然后列出其内容图 5 中的标记 1。可以看到它包含许多以两个字符的十六进制值命名的文件夹。为了避免超出操作系统允许的文件夹内含文件数量Git 将从所有 40 个字节的 SHA-1 值中删除的前两个字符用作文件夹名称然后使用剩下的 38 个字符作为要存储的对象的文件名。举例来说我项目中第一次提交的提交 ID 为 a759f283因此对象所在文件夹的名称为 a7ID 的前两个字符。与预期一样当我打开此文件夹时看到了名为 59f283 的文件。请注意这些以十六进制命名的文件夹中存储的所有文件都是 Git 对象。为节省空间Git 使用 zlib 压缩对象存储中的文件。由于这种压缩会生成二进制文件因此无法使用文本编辑器来查看这些文件。相反需要调用 Git 命令从而正确解压缩 Git 对象数据并使用能够理解的格式来呈现数据。 图 5使用 Git 命令行接口探索 Git 对象 我已知道文件 59f283 包含一个提交对象因为这是提交 ID。但有时会在 objects 文件夹中看到不知道是什么的文件。Git 提供 cat-file 底层命令来报告对象类型以及所含内容标记 3。若要获取类型请在调用命令时指定 -t类型选项以及 Git 对象文件名的几个惟一字符 git cat-file -t a759f2 在我的系统中此命令报告的值为“commit”表明以 a759f2 开头的文件包含提交对象。虽然仅指定 SHA-1 哈希值的前 5 个字符通常就足够了但也可以根据需要提供任意数量的字符不要忘记添加文件夹名称中的两个字符。使用 -p优质打印选项发出同一命令后Git 会从提交对象提取信息然后以清晰明了的格式呈现这些信息标记 4。 提交对象包含以下属性 父提交 ID、树 ID、作者姓名、作者电子邮件地址、作者提交时间戳、提交者姓名、提交者电子邮件地址、提交者提交时间戳和提交消息存储库中的第一次提交不显示父提交 ID。每个提交对象的 SHA-1 都是根据这些提交对象属性中包含的所有值计算得出这实际上保证了每个提交对象都有一个惟一提交 ID。 树和 blob 对象请注意尽管提交对象包含提交的相关信息但并不包含任何文件或文件夹。相反包含的是指向 Git 树对象的树 ID也是 SHA-1 值。树对象和其他所有 Git 对象都存储在 .git\objects 文件夹中。 图 6 展示了每个提交对象包含的根树对象。根树对象进而根据需要映射到 blob 对象接下来我将介绍和其他树对象。 图 6直观呈现表示提交的 Git 对象 由于我的项目中的第二次提交提交 ID 为 bfeb09包括文件和文件夹见上面的图 4因此我将用它来说明树对象的工作方式。图 7 中的标记 1 展示了 cat‑file ‑p bfeb09 输出。这一次请注意其中包含可正确引用第一个提交对象的 SHA-1 值的父属性。请注意此为提交对象的父引用以便 Git 能够构造和维护提交 DAG。 图 7使用 Git CLI 探索树对象详细信息 根树对象进而根据需要映射到 blob 对象使用 zlib 压缩的文件和其他树对象。 提交 bfeb09 包含 ID 为 ca853d 的树属性。图 7 中的标记 2 展示了 cat-file -p ca853d 输出。每个树对象包含与对象的 POSIX 权限掩码040000 目录、100644 常规不可执行文件、100664 常规不可执行组可写文件、100755 常规可执行文件、120000 符号链接和 160000 Gitlink对应的权限属性、类型树或 blob、SHA-1对于树或 blob和名称。名称是文件夹名称对于树对象或文件名对于 blob 对象。观察发现此树对象由 3 个 blob 对象和另一个树对象组成。可以看到这 3 个 blob 分别指的是文件 .gitattributes、.gitignore 和 DemoConsole.sln而树指的是文件夹 DemoConsoleApp图 7 中的标记 3。尽管树对象 ca853d 与项目的第二次提交相关联但它的前两个 blob 表示第一次提交时添加的文件 .gitattributes 和 .gitignore见图 4 中的标记 1 这些文件之所以会出现在第二次提交的树中是因为每次提交表示的是上一个提交对象以及当前提交对象捕获的更改。若要更深入地“遍历树”请参阅图 7 中的标记 3其中展示了 cat-file -p a763da 输出包含另外 3 个 blobApp.config、emoConsoleApp.csproj 和 Program.cs和另一个树文件夹属性。 blob 对象也是直接使用 zlib 进行压缩的文件。如果未压缩的文件包含文本可以使用相同的 cat-file 命令和 blob ID 提取 blob 的全部内容图 7 中的标记 5。由于 blob 对象表示的是文件因此 Git 使用 SHA-1 blob ID来确定文件是否自上次提交后发生变化还使用 SHA-1 值对存储库中的任意两次提交进行差异对比。 标记对象鉴于 SHA-1 值的加密字母数字性沟通起来可能有点难。使用标记对象可以为任何提交、树或 blob 对象分配易记名称尽管最常见的做法是只标记提交对象。标记对象的类型分为以下两种轻量级和注释。这两种类型的对象都作为 .git\refs\tags 文件夹中的文件显示其中标记名称就是文件名。轻量级标记文件的内容是现有提交、树或 blob 对象的 SHA-1。注释标记文件的内容是与其他所有 Git 对象一同存储在 .git\objects 文件夹中的标记对象的 SHA-1。若要查看标记对象的内容可以使用相同的 cat-file -p 命令。可以看到标记对象的 SHA-1 值以及对象类型、标记作者、日期时间和标记消息。在 Visual Studio 中可以通过许多种方法来标记提交。一种方法是单击“提交详细信息”窗口见上面图 3 中的标记 3中的“创建标记”链接。“提交详细信息”窗口见上面图 3 中的标记 3和“查看修订记录报告”见上面图 3 中的标记 9中显示了标记名称。 向存储库中的对象应用存储优化时Git 会在 .git\objects 文件夹中填充信息和包文件夹。我将在近期发表的文章中更全面地介绍这些文件夹和 Git 文件存储优化。 了解这 4 种类型的 Git 对象后我发现可以将 Git 称为“内容可寻址的文件系统”因为任意数量文件和文件夹中的任何类型内容都可以简化成一个 SHA-1 值。稍后可以使用相应的 SHA-1 值准确可靠地重新创建同一内容。从另一个角度来说在惯常的密钥索引驱动查找表的高级实现中SHA-1 是键内容是值。此外如果文件内容在两次提交之间没有发生变化Git 可以节省开支因为未发生变化的文件生成的 SHA-1 值相同。也就是说提交对象可以引用上一次提交使用的相同 SHA-1 blob 或树 ID 值而无需新建任何对象即无需新建文件副本 分支 必须先了解 Git 是如何在内部定义分支的才能真正理解什么是 Git 分支。总的来说这归结为理解以下两个关键词的用途头和 HEAD。 第一个关键词“头”英文为全部字母小写是 Git 为每个新建的提交对象维护的引用。为了阐明具体工作方式图 8 展示了多个提交和分支操作。对于提交 01Git 为存储库创建了第一个头引用并将其默认命名为“master”master 是没有任何特殊含义的任意名称只是一个默认名称而已Git 团队经常会重命名此引用。新建头引用后Git 会在 ref\heads 文件夹中创建一个文本文件并将新提交对象的完整 SHA‑1 置于此文件中。对于提交 01也就是说Git 会创建一个名为“master”的文件并将提交对象 A1 的 SHA-1 置于此文件中。对于提交 02Git 会删除旧 SHA-1 值并将其替换成 A2 的完整 SHA-1 提交 ID从而更新 heads 文件夹中的 master 头文件。Git 会对提交 03 执行相同操作 它会将 heads 文件夹中的 master 头文件更新为包含 A3 的完整提交 ID。 图 82 个头好过 1 个头Git 在 heads 文件夹中维护各种文件以及一个 HEAD 文件 大家可能已经猜到heads 文件夹中的 master 文件就是它指向的提交对象的分支名称。奇怪的是分支名称也许最初指向一个提交对象而不是一系列提交对象我很快就会详细介绍这一特定概念。 请观察图 8 中的“创建分支和签出文件”部分。其中用户在 Visual Studio 中为打印预览功能新建了一个分支。用户将此分支命名为 feat_print_preview让其以 master 为依据然后在团队资源管理器的“从选定项创建本地分支”窗格中选中了“签出分支”复选框。选中此复选框即指示 Git 要让新分支成为当前分支我很快就会对此进行解释。在后台Git 在 heads 文件夹中新建了一个 feat_print_preview 头文件并将提交对象 A3 的 SHA-1 值置于其中。也就是说现在 heads 文件夹中包含以下两个文件master 和 feat_print_preview。这两个文件都指向 A3。 在提交 04 中Git 需要做出一项决定 通常情况下它会更新 heads 文件夹中文件引用的 SHA-1 值。而现在此文件夹中有两个文件引用该更新哪个文件引用呢 此时HEAD 就派上用场了。HEAD所有字母大写是 .git 文件夹根目录下的一个文件指向 heads 文件夹中的头英文为全部字母小写文件。请注意“HEAD”实际上就是一个一直被命名为 HEAD 的文件而“头”文件则没有特定的名称。 头文件 HEAD 包含将分配为下一个提交对象的父 ID 的提交 ID。实际上HEAD 标记的是 Git 当前在 DAG 上的位置。也就是说可能有很多头但始终只有一个 HEAD。 再回到图 8提交 01 显示 HEAD 指向 master 头文件进而指向 A1也就是说master 头文件包含提交对象 A1 的 SHA-1。在提交 02 中Git 不需要对 HEAD 文件执行任何操作因为 HEAD 已经指向文件 master。提交 03 同上。不过在“创建和签出新分支”步骤中用户创建了一个分支并通过选中“签出分支”复选框签出了分支文件。作为响应Git 将 HEAD 更新为指向 feat_print_preview 头文件而不是 master。如果用户没有选中“签出分支”复选框那么 HEAD 会继续指向 master。 了解 HEAD 后现在可以看到提交 04 不再需要 Git 做出任何决定 Git 只需检查 HEAD 的值发现它指向的是 feat_print_preview 头文件。然后便确定必须将 feat_print_preview 头文件中的 SHA-1 更新为包含 B1 的提交 ID。 在“签出分支”步骤中用户访问了团队资源管理器的“分支”窗格右键单击了“主分支”然后选择了“签出”。作为响应Git 签出提交 A3 的文件并将 HEAD 文件更新为指向 master 头文件。 此时应该非常清楚为什么 Git 中的分支操作如此高效快速 新建分支可以归结为创建一个文本文件头文件和更新另一个文本文件 (HEAD)。切换分支只涉及更新一个文本文件 (HEAD)造成的性能影响通常很小因为工作目录中的文件是从存储库进行更新。 请注意提交对象不包含任何分支信息 实际上仅通过 HEAD 文件和 heads 文件夹中用作引用的各种文件来维护分支。然而使用 Git 的开发者在谈到分支或引用分支时口语上通常指的是源自 master 或新组建的分支的一系列提交对象。上面的图 2 展示了许多开发者可以确定的三个分支 A、B 和 C。分支 A 从 A1 一直到 A6。A4 处的分支活动生成了两个新分支 B1 和 C1。因此可以将从 B1 一直到 B3 的提交称为分支 B而将从 C1 一直到 C2 的提交称为分支 C。 这里得出的结论是不要忘记 Git 分支的形式定义 就是指向提交对象的指针。此外Git 维护所有分支称为“头”的分支指针和当前分支称为“HEAD”的一个分支指针。 Jonathan Waldman 是一名 Microsoft 认证专家专攻软件工效学从 Microsoft 技术诞生之际便一直研究这些技术。Waldman 是 Pluralsight 技术团队的成员目前负责机构和私企软件开发项目。可以通过 jonathan.waldmanlive.com 与他联系。
原文地址https://msdn.microsoft.com/en-us/magazine/mt809117 .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注