<!DOCTYPE html><html lang="zh" data-theme="dark"><head><meta charset="utf-8"><meta name="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>IBM 全栈开发【12】:Git 和 GitHub 入门 · Cytrogen 的个人博客</title><meta name="description" content="本文是 IBM 全栈开发课程的第十二篇学习笔记,详细介绍了版本控制工具 Git 与代码托管平台 GitHub 的入门知识。笔记内容从版本控制的核心理念讲起,涵盖了仓库、分支、提交、拉取请求等基本概念,并系统梳理了 git clone, commit, push, merge 等常用命令行操作。最后,通过一个完整的毕业项目,手把手指导读者分别使用 GitHub 网页界面和 Git 命令行(CLI)完成创建仓库、修复 Bug、分支管理和发起拉取请求的完整协作流程,为初学者提供了从理论到实战的全面指南。"><link rel="icon" href="../favicon.png"><link rel="canonical" href="https://cytrogen.icu/posts/369.html"><link rel="webmention" href="https://webmention.io/cytrogen.icu/webmention"><link rel="me" href="https://m.otter.homes/@Cytrogen"><link rel="me" href="https://github.com/cytrogen"><meta name="fediverse:creator" content="@Cytrogen@m.otter.homes"><link rel="preload" href="../fonts/opensans-regular-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous"><style>@font-face {
font-family: 'Open Sans';
src: url('../fonts/opensans-regular-latin.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
size-adjust: 107%;
ascent-override: 97%;
descent-override: 25%;
line-gap-override: 0%;
}
</style><script>(function() {
try {
// 优先级:用户选择 > 系统偏好 > 默认浅色
const saved = localStorage.getItem('theme');
const theme = saved ||
(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
} catch (error) {
// 失败时使用默认主题,不阻塞渲染
document.documentElement.setAttribute('data-theme', 'light');
}
})();
</script><link rel="stylesheet" href="../css/ares.css"><script data-netlify-skip-bundle="true">(function() {
document.addEventListener('DOMContentLoaded', function() {
const theme = document.documentElement.getAttribute('data-theme');
const pageWrapper = document.getElementById('page-wrapper');
if (pageWrapper && theme) {
pageWrapper.setAttribute('data-theme', theme);
}
});
})();
</script><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="atom.xml" title="Cytrogen 的个人博客" type="application/atom+xml">
</head><body><div id="page-wrapper"><a class="skip-link" href="#main-content">跳到主要内容</a><div class="wrap"><header><a class="logo-link" href="../index.html"><img src="../favicon.png" alt="logo"></a><div class="h-card visually-hidden"><img class="u-photo" src="https://cytrogen.icu/favicon.png" alt="Cytrogen"><a class="p-name u-url u-uid" href="https://cytrogen.icu">Cytrogen</a><p class="p-note">Cytrogen 的个人博客,Cytrogen's Blog</p><a class="u-url" rel="me noopener" target="_blank" href="https://m.otter.homes/@Cytrogen">Mastodon</a><a class="u-url" rel="me noopener" target="_blank" href="https://github.com/cytrogen">GitHub</a></div><nav class="site-nav"><div class="nav-main"><div class="nav-primary"><ul class="nav-list hidden-mobile"><li class="nav-item"><a class="nav-link" href="../index.html">首页</a></li></ul><div class="nav-tools"><div class="language-menu"><button class="language-toggle" type="button"><svg class="icon icon-globe" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855A7.97 7.97 0 0 0 10.855 12H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z"></path></svg><span>中文</span></button><div class="language-dropdown"></div></div></div><div class="nav-controls"><div class="more-menu hidden-mobile"><button class="more-toggle" type="button"><span>更多</span><svg class="icon icon-chevron-down" width="12" height="12" viewBox="0 0 12 12" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 8.825c-.2 0-.4-.1-.5-.2l-3.3-3.3c-.3-.3-.3-.8 0-1.1s.8-.3 1.1 0l2.7 2.7 2.7-2.7c.3-.3.8-.3 1.1 0s.3.8 0 1.1l-3.3 3.3c-.1.1-.3.2-.5.2z"></path></svg></button><div class="more-dropdown"><ul class="dropdown-list"><li class="dropdown-item"><a class="nav-link" href="../archives/index.html">归档</a></li><li class="dropdown-item"><a class="nav-link" href="../categories/index.html">分类</a></li><li class="dropdown-item"><a class="nav-link" href="../tags/index.html">标签</a></li><li class="dropdown-item"><a class="nav-link" href="../about/index.html">关于</a></li><li class="dropdown-item"><a class="nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></div><div class="theme-switcher"><button class="theme-toggle" type="button" role="switch" aria-pressed="false" aria-label="切换主题"><div class="theme-icon moon-icon"><svg class="icon icon-moon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path></svg></div><div class="theme-icon sun-icon"><svg class="icon icon-sun" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"></path></svg></div></button></div><details class="mobile-menu-details hidden-desktop"><summary class="hamburger-menu" aria-label="nav.menu"><svg class="icon icon-bars" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"></path></svg><span class="menu-text">nav.menu</span></summary><div class="mobile-menu-dropdown"><ul class="mobile-nav-list"><li class="mobile-nav-item"><a class="mobile-nav-link" href="../index.html">首页</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../archives/index.html">归档</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../categories/index.html">分类</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../tags/index.html">标签</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../about/index.html">关于</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></details></div></div></div></nav></header><main class="container" id="main-content" tabindex="-1"><div class="post"><article class="post-block h-entry"><div class="post-meta p-author h-card visually-hidden"><img class="author-avatar u-photo" src="../favicon.png" alt="Cytrogen"><span class="p-name">Cytrogen</span><a class="u-url" href="https://cytrogen.icu">https://cytrogen.icu</a></div><a class="post-permalink u-url u-uid visually-hidden" href="https://cytrogen.icu/posts/369.html">永久链接</a><div class="p-summary visually-hidden"><p>近期在学习 IBM 全栈应用开发微学士课程,故此记录学习笔记。</p>
<p>唉,本来还剩一个证就考完了,结果原先十二个证的微学士学位路线被标过期,最新的路线新添了这个 Git 和 GitHub 入门的证,100 美元喜减一。</p></div><div class="visually-hidden"><a class="p-category" href="../categories/%E7%BC%96%E7%A8%8B%E7%AC%94%E8%AE%B0/">编程笔记</a><a class="p-category" href="../tags/IBM/">IBM</a><a class="p-category" href="../tags/Git/">Git</a><a class="p-category" href="../tags/GitHub/">GitHub</a></div><h1 class="post-title p-name">IBM 全栈开发【12】:Git 和 GitHub 入门</h1><div class="post-info"><time class="post-date dt-published" datetime="2024-06-28T03:54:00.000Z">6/27/2024</time><time class="dt-updated visually-hidden" datetime="2026-02-09T17:16:54.717Z"></time></div><div class="post-content e-content"><html><head></head><body><p>近期在学习 IBM 全栈应用开发微学士课程,故此记录学习笔记。</p>
<p>唉,本来还剩一个证就考完了,结果原先十二个证的微学士学位路线被标过期,最新的路线新添了这个 Git 和 GitHub 入门的证,100 美元喜减一。</p>
<span id="more"></span>
<h1 id="1-git-和-github-基础知识"><a class="markdownIt-Anchor" href="#1-git-和-github-基础知识"></a> 1. Git 和 GitHub 基础知识</h1>
<p>应用程序开发人员很少单独工作。大型网络/云/移动开发和数据科学项目将包括许多人 —— 前端开发员、后端开发员、数据库管理员、存储库管理员等。必须跟踪和控制每个贡献者的每次更改,以实现协作、问责制和版本管理。这种分布式版本控制在管理小型和大型软件项目时都极为重要。</p>
<p>在本模块中,你将了解一些流行的版本控制工具,创建一个 GitHub 账户,并使用 GitHub 网页界面创建一个仓库,向其中添加文件并提交更改。在 GitHub 等基于 Git 的版本控制系统中,分支是工作流程的核心。您还将熟悉创建和使用分支,并将更改合并到主分支。</p>
<p>学习目标:</p>
<ul>
<li>定义分布式版本控制。</li>
<li>列出用于版本控制的几种工具,包括流行的 Git 平台。</li>
<li>描述 Git 的基本概念和仓库的目的。</li>
<li>在你的仓库中添加 / 编辑文件,并使用 GitHub 网页界面提交修改。</li>
<li>创建 GitHub 账户和仓库。</li>
<li>解释如何使用分支并描述拉取请求。</li>
<li>使用 GitHub Web 界面创建 GitHub 分支并执行合并操作。</li>
</ul>
<h2 id="11-git-和-github-概述"><a class="markdownIt-Anchor" href="#11-git-和-github-概述"></a> 1.1. Git 和 GitHub 概述</h2>
<p>Git 和 GitHub 是深受开发人员和数据科学家欢迎的环境,但如果不了解版本控制的基本知识,就无法讨论它们。</p>
<p>版本控制系统可让您跟踪对源代码的更改。这样,如果您犯了错误,就可以很容易地恢复旧版本的文档。此外,它还能让与其他团队成员的协作变得更加容易。</p>
<p>用一个例子来说明版本控制是如何工作的:假设你有一份购物清单,希望室友们确认你需要的东西并添加其他物品。如果没有版本控制,在去购物之前就会有一大堆乱七八糟的东西要收拾,而有了版本控制,在每个人都献计献策之后,你就能清楚地知道自己需要什么。</p>
<p>Git 是根据通用公共许可证或 GNU 发布的免费开源软件。它是一种分布式版本控制系统(或称 DVCS),这意味着世界上任何地方的用户都可以在自己的电脑上拥有项目的副本。当他们进行修改时,他们可以将自己的版本同步到远程服务器,与你共享。</p>
<p>Git 并不是唯一的版本控制系统,但它的分布式特性是其成为最流行版本控制系统的主要原因之一。版本控制系统广泛应用于涉及代码的事务,但你也可以对图像、文档和任何文件类型进行版本控制。请注意,Git 还支持分支策略,如功能分支,以组织和管理开发工作。</p>
<p>GitHub 是最受欢迎的 Git 仓库网络托管服务之一。其他服务包括 Git Lab、Bitbucket 和 Beanstock。</p>
<p>在开始之前,你需要了解一些基本术语:</p>
<ul>
<li>Secure Shell 或简称 SSH 协议是一种从一台计算机安全远程登录到另一台计算机的方法。</li>
<li>Fork 是一个仓库的副本。</li>
<li>拉取请求(Pull Request 或简称 PR)是指你请求他人在你的修改成为最终版本之前对其进行审核和批准。</li>
<li>工作目录(Working Directory)包含计算机上与 Git 仓库相关联的文件和子目录。</li>
<li>提交(Commit)是项目当前状态在某个特定时间点的快照,并附有所做改动的说明。</li>
<li>分支(Branch)是一条独立的开发线,可以让你独立完成功能或修正。</li>
<li>合并(Merge)是将一个分支中的改动合并到另一个分支中,通常是将特性分支合并到主分支中。</li>
<li>克隆(Clone)会在你的电脑上创建一个远程 Git 仓库的本地副本。</li>
</ul>
<h4 id="111-github-入门"><a class="markdownIt-Anchor" href="#111-github-入门"></a> 1.1.1. GitHub 入门</h4>
<p>2000 年代初,Linux 的开发由一个名为 BitKeeper 的免费系统管理。2005 年,BitKeeper 转为收费系统,出于多种原因,这给 Linux 开发人员带来了麻烦。Linus Torvalds 带领团队开发了一个替代的源代码版本控制系统。该项目在很短的时间内完成,主要特点由一个小组确定。其中包括:</p>
<ul>
<li>对非线性开发的强大支持。(当时,Linux 补丁以每秒 6.7 个的速度到达)</li>
<li>分布式开发。每个开发人员都可以拥有一份完整开发历史的本地副本。</li>
<li>与现有系统和协议兼容。这是承认 Linux 社区多样性的必要条件。</li>
<li>高效处理大型项目。</li>
<li>历史加密验证。这确保分布式系统的代码更新完全一致。</li>
<li>可插拔的合并策略。许多开发途径都可能导致复杂的整合决策,可能需要明确的整合战略。</li>
</ul>
<p>Git 仓库模型有什么特别之处?Git 是一个分布式版本控制系统。主要用于在开发过程中跟踪源代码。它包含在程序员之间进行协调、跟踪更改和支持非线性工作流程的元素。由 Linus Torvalds 于 2005 年创建,用于发布 Linux 内核。</p>
<p>Git 是一个分布式版本控制系统,用于跟踪内容变更。它是协作的中心点,尤其侧重于敏捷开发方法。在中央版本控制系统中,每个开发人员都需要从中央系统中签出代码并提交到中央系统中。由于 Git 是一种分布式版本控制系统,每个开发人员都有一份完整开发历史的本地副本,而且变更会从一个仓库复制到另一个仓库。每个开发人员都可以充当中枢。如果正确使用 Git,就会有一个与可部署代码相对应的主分支。团队可以持续整合已准备好发布的变更,并在两次发布之间同时在不同的分支上工作。</p>
<p>Git 还允许对任务进行集中管理,并对每个团队进行访问级别控制。Git 可通过 GitHub 桌面客户端等方式在本地使用,也可直接通过连接到 GitHub 网页界面的浏览器使用。IBM 云基于完善和成熟的开源工具,包括 Git 仓库(通常称为 repos)。</p>
<p>GitHub 是 Git 仓库的在线托管服务。GitHub 由微软的一家子公司托管。GitHub 提供免费、专业和企业账户。截至 2019 年 8 月,GitHub 拥有超过 1 亿个仓库。</p>
<p>仓库是用于存储文件(包括应用程序源代码)的数据结构。仓库可以跟踪和维护版本控制。</p>
<p>GitLab 是一个完整的 DevOps 平台,以单个应用程序的形式交付。GitLab 可访问由源代码管理控制的 Git 代码库。通过 GitLab,开发人员可以协作、审查代码、发表评论并帮助改进彼此的代码。使用自己的本地代码副本工作。在需要时对代码进行分支和合并。利用内置的持续集成(Cl)和持续交付(CD)简化测试和交付。</p>
<h4 id="112-github-分支"><a class="markdownIt-Anchor" href="#112-github-分支"></a> 1.1.2. GitHub 分支</h4>
<div class="danger">
<p>本课内有关注册 GitHub 账户和创建 GitHub 仓库的内容被我跳过了,建议去网上搜索相关的教程。</p>
</div>
<p>GitHub 中的所有文件都存储在一个分支中。主分支是确定的,它存储的是代码的可部署版本。主分支是默认创建的,但你也可以使用任何分支作为代码的主要、完成和可部署版本。当你计划更改内容时,可以创建一个新的分支,并给它起一个描述性的名字。新分支一开始就是原始分支的完全副本。当你进行更改时,你创建的分支会保留更改后的代码。</p>
<p>要创建新分支,请单击下拉菜单 <code>Main</code>,在新分支文本中添加新分支名称,然后选择 <code>Create Branch</code>。</p>
<p>对于大型软件项目来说,GitHub 分支可能非常复杂。对于我们正在探索的这种简单项目,可以考虑以下方法:从一个共同的基础开始,也就是这个项目的初始源。在开发新功能时,代码会被分支。</p>
<p>举个例子,两个分支都在进行修改。当两个工作流准备好合并时,每个分支的代码都会被识别为一个提示(tip),然后将两个提示合并为第三个合并分支。</p>
<svg aria-roledescription="gitGraph" role="graphics-document document" viewBox="-117.1484375 -49 575.1484375 204.9535369873047" height="204.9535369873047" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="575.1484375" id="mermaid-1771490033715"><style>#mermaid-1771490033715{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-1771490033715 .error-icon{fill:#552222;}#mermaid-1771490033715 .error-text{fill:#552222;stroke:#552222;}#mermaid-1771490033715 .edge-thickness-normal{stroke-width:2px;}#mermaid-1771490033715 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1771490033715 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1771490033715 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1771490033715 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1771490033715 .marker{fill:#333333;stroke:#333333;}#mermaid-1771490033715 .marker.cross{stroke:#333333;}#mermaid-1771490033715 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-1771490033715 .commit-id,#mermaid-1771490033715 .commit-msg,#mermaid-1771490033715 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms',verdana,arial,sans-serif;font-family:var(--mermaid-font-family);}#mermaid-1771490033715 .branch-label0{fill:#ffffff;}#mermaid-1771490033715 .commit0{stroke:hsl(240, 100%, 46.2745098039%);fill:hsl(240, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight0{stroke:hsl(60, 100%, 3.7254901961%);fill:hsl(60, 100%, 3.7254901961%);}#mermaid-1771490033715 .label0{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow0{stroke:hsl(240, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label1{fill:black;}#mermaid-1771490033715 .commit1{stroke:hsl(60, 100%, 43.5294117647%);fill:hsl(60, 100%, 43.5294117647%);}#mermaid-1771490033715 .commit-highlight1{stroke:rgb(0, 0, 160.5);fill:rgb(0, 0, 160.5);}#mermaid-1771490033715 .label1{fill:hsl(60, 100%, 43.5294117647%);}#mermaid-1771490033715 .arrow1{stroke:hsl(60, 100%, 43.5294117647%);}#mermaid-1771490033715 .branch-label2{fill:black;}#mermaid-1771490033715 .commit2{stroke:hsl(80, 100%, 46.2745098039%);fill:hsl(80, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight2{stroke:rgb(48.8333333334, 0, 146.5000000001);fill:rgb(48.8333333334, 0, 146.5000000001);}#mermaid-1771490033715 .label2{fill:hsl(80, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow2{stroke:hsl(80, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label3{fill:#ffffff;}#mermaid-1771490033715 .commit3{stroke:hsl(210, 100%, 46.2745098039%);fill:hsl(210, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight3{stroke:rgb(146.5000000001, 73.2500000001, 0);fill:rgb(146.5000000001, 73.2500000001, 0);}#mermaid-1771490033715 .label3{fill:hsl(210, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow3{stroke:hsl(210, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label4{fill:black;}#mermaid-1771490033715 .commit4{stroke:hsl(180, 100%, 46.2745098039%);fill:hsl(180, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight4{stroke:rgb(146.5000000001, 0, 0);fill:rgb(146.5000000001, 0, 0);}#mermaid-1771490033715 .label4{fill:hsl(180, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow4{stroke:hsl(180, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label5{fill:black;}#mermaid-1771490033715 .commit5{stroke:hsl(150, 100%, 46.2745098039%);fill:hsl(150, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight5{stroke:rgb(146.5000000001, 0, 73.2500000001);fill:rgb(146.5000000001, 0, 73.2500000001);}#mermaid-1771490033715 .label5{fill:hsl(150, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow5{stroke:hsl(150, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label6{fill:black;}#mermaid-1771490033715 .commit6{stroke:hsl(300, 100%, 46.2745098039%);fill:hsl(300, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight6{stroke:rgb(0, 146.5000000001, 0);fill:rgb(0, 146.5000000001, 0);}#mermaid-1771490033715 .label6{fill:hsl(300, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow6{stroke:hsl(300, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch-label7{fill:black;}#mermaid-1771490033715 .commit7{stroke:hsl(0, 100%, 46.2745098039%);fill:hsl(0, 100%, 46.2745098039%);}#mermaid-1771490033715 .commit-highlight7{stroke:rgb(0, 146.5000000001, 146.5000000001);fill:rgb(0, 146.5000000001, 146.5000000001);}#mermaid-1771490033715 .label7{fill:hsl(0, 100%, 46.2745098039%);}#mermaid-1771490033715 .arrow7{stroke:hsl(0, 100%, 46.2745098039%);}#mermaid-1771490033715 .branch{stroke-width:1;stroke:#333333;stroke-dasharray:2;}#mermaid-1771490033715 .commit-label{font-size:10px;fill:#000021;}#mermaid-1771490033715 .commit-label-bkg{font-size:10px;fill:#ffffde;opacity:0.5;}#mermaid-1771490033715 .tag-label{font-size:10px;fill:#131300;}#mermaid-1771490033715 .tag-label-bkg{fill:#ECECFF;stroke:hsl(240, 60%, 86.2745098039%);}#mermaid-1771490033715 .tag-hole{fill:#333;}#mermaid-1771490033715 .commit-merge{stroke:#ECECFF;fill:#ECECFF;}#mermaid-1771490033715 .commit-reverse{stroke:#ECECFF;fill:#ECECFF;stroke-width:3;}#mermaid-1771490033715 .commit-highlight-inner{stroke:#ECECFF;fill:#ECECFF;}#mermaid-1771490033715 .arrow{stroke-width:8;stroke-linecap:round;fill:none;}#mermaid-1771490033715 .gitTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-1771490033715 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g></g><g class="commit-bullets"></g><g class="commit-labels"></g><g><line class="branch branch0" y2="0" x2="450" y1="0" x1="0"></line><rect transform="translate(-19, -8.5)" height="21" width="52.6875" y="-0.5" x="-68.6875" ry="4" rx="4" class="branchLabelBkg label0"></rect><g class="branchLabel"><g transform="translate(-78.6875, -9.5)" class="label branch-label0"><text><tspan class="row" x="0" dy="1em" xml:space="preserve">main</tspan></text></g></g><line class="branch branch1" y2="90" x2="450" y1="90" x1="0"></line><rect transform="translate(-19, 81.5)" height="21" width="74.1484375" y="-0.5" x="-90.1484375" ry="4" rx="4" class="branchLabelBkg label1"></rect><g class="branchLabel"><g transform="translate(-100.1484375, 80.5)" class="label branch-label1"><text><tspan class="row" x="0" dy="1em" xml:space="preserve">develop</tspan></text></g></g></g><g class="commit-arrows"><path class="arrow arrow0" d="M 10 0 L 60 0"></path><path class="arrow arrow1" d="M 60 0 L 60 70 A 20 20, 0, 0, 0, 80 90 L 110 90"></path><path class="arrow arrow1" d="M 110 90 L 160 90"></path><path class="arrow arrow1" d="M 160 90 L 210 90"></path><path class="arrow arrow0" d="M 60 0 L 260 0"></path><path class="arrow arrow0" d="M 260 0 L 310 0"></path><path class="arrow arrow0" d="M 310 0 L 360 0"></path><path class="arrow arrow1" d="M 210 90 L 340 90 A 20 20, 0, 0, 0, 360 70 L 360 0"></path><path class="arrow arrow0" d="M 360 0 L 410 0"></path></g><g class="commit-bullets"><circle class="commit Common base commit0" r="10" cy="0" cx="10"></circle><circle class="commit 1-4fd836f commit0" r="10" cy="0" cx="60"></circle><circle class="commit 2-8ca73e0 commit1" r="10" cy="90" cx="110"></circle><circle class="commit 3-0af72fb commit1" r="10" cy="90" cx="160"></circle><circle class="commit Feature tip commit1" r="10" cy="90" cx="210"></circle><circle class="commit 5-11c4ee0 commit0" r="10" cy="0" cx="260"></circle><circle class="commit 6-2ee7098 commit0" r="10" cy="0" cx="310"></circle><circle class="commit 7-eb79545 commit0" r="9" cy="0" cx="360"></circle><circle class="commit commit-merge 7-eb79545 commit0" r="6" cy="0" cx="360"></circle><circle class="commit New merge commit commit0" r="10" cy="0" cx="410"></circle></g><g class="commit-labels"><g transform="translate(-36.17775390625, 32.259042968749995) rotate(-45, 0, 0)"><rect height="15" width="69.4677734375" y="13.5" x="-24.73388671875" class="commit-label-bkg"></rect><text class="commit-label" y="25" x="-22.73388671875">Common base</text></g><g transform="translate(-27.44146484375, 24.442363281250003) rotate(-45, 50, 0)"><rect height="15" width="46.4775390625" y="13.5" x="36.76123046875" class="commit-label-bkg"></rect><text class="commit-label" y="25" x="38.76123046875">1-4fd836f</text></g><g transform="translate(-29.425703125000002, 26.217734375) rotate(-45, 100, 90)"><rect height="15" width="51.69921875" y="103.5" x="84.150390625" class="commit-label-bkg"></rect><text class="commit-label" y="115" x="86.150390625">2-8ca73e0</text></g><g transform="translate(-27.523847656250002, 24.51607421875) rotate(-45, 150, 90)"><rect height="15" width="46.6943359375" y="103.5" x="136.65283203125" class="commit-label-bkg"></rect><text class="commit-label" y="115" x="138.65283203125">3-0af72fb</text></g><g transform="translate(-29.63166015625, 26.40201171875) rotate(-45, 200, 90)"><rect height="15" width="52.2412109375" y="103.5" x="183.87939453125" class="commit-label-bkg"></rect><text class="commit-label" y="115" x="185.87939453125">Feature tip</text></g><g transform="translate(-29.425703125000002, 26.217734375) rotate(-45, 250, 0)"><rect height="15" width="51.69921875" y="13.5" x="234.150390625" class="commit-label-bkg"></rect><text class="commit-label" y="25" x="236.150390625">5-11c4ee0</text></g><g transform="translate(-29.639082031250002, 26.40865234375) rotate(-45, 300, 0)"><rect height="15" width="52.2607421875" y="13.5" x="283.86962890625" class="commit-label-bkg"></rect><text class="commit-label" y="25" x="285.86962890625">6-2ee7098</text></g><g transform="translate(-44.1128515625, 39.358867187499996) rotate(-45, 400, 0)"><rect height="15" width="90.349609375" y="13.5" x="364.8251953125" class="commit-label-bkg"></rect><text class="commit-label" y="25" x="366.8251953125">New merge commit</text></g></g><text class="gitTitleText" y="-25" x="170.42578125">Example Git diagram</text></svg>
<p>开发人员在分支中处理源文件。由于有些项目需要一段时间,源文件并不能立即发挥作用。要更改文件内容,需要选择文件,点击铅笔图标,进行更改,然后提交更改。当开发人员完成指定的工作后,为了保存他们的修改,他们会提交代码。提交表示开发人员确信代码代表了正在开发的功能或功能集的稳定平台。</p>
<p>当开发人员将变更源提交到自己的路径时,他们需要写一个注释来描述变更。注释应具有意义和描述性。开发人员可以选择提交到当前分支或创建一个新分支。最后,点击 <code>Commit Changes</code>。</p>
<p>写注释时的一些最佳做法:不要用句号结束评论信息;提交信息的字符数不要超过 50 个;使用扩展窗口了解详情;始终使用主动语态。</p>
<p>拉取用于启动分支合并,以捕捉变更。拉取请求会将提交的修改建议提供给其他人审查和使用。即使代码尚未完成,也可以在任何提交后进行拉取。拉取需要用户批准更改。该用户可以是变更的作者,也可以是团队中的指定人员。</p>
<blockquote>
<p>请注意,如果你在不属于你的分支上做了改动,GitHub 会自动以你的名义提出拉取请求。由于日志文件不可更改,因此总能找到批准合并变更的人。</p>
</blockquote>
<p>要打开拉取请求,请单击 <code>Pull Requests</code> 并选择 <code>New Pull Request</code>:</p>
<ol>
<li>从比较框中选择新分支。</li>
<li>向下滚动查看变更。</li>
<li>确认这些更改就是你要评估的内容。</li>
<li>为请求添加标题和描述。</li>
<li>点击 <code>Create Pull Request</code>。</li>
</ol>
<p>Git 仓库的目的是让主分支成为唯一部署的代码。开发人员可以修改分支中的源文件,但只有提交后才会发布。拉取命令发出后,代码会被审核和批准。审核通过的代码会被合并回主代码。</p>
<p>要将已提交的代码变更合并到主代码中,请单击 <code>Merge Pull Request</code>,然后单击 <code>Confirm Merge</code>。当某个分支的所有变更完成后,该分支将被视为过时,应予以删除。</p>
<h1 id="2-分支-git-命令和管理-github-项目"><a class="markdownIt-Anchor" href="#2-分支-git-命令和管理-github-项目"></a> 2. 分支、Git 命令和管理 GitHub 项目</h1>
<p>当你开始使用 GitHub 仓库并自动化工作流程时,使用网页界面可能会受到限制,而且更耗时。这就是 Git 命令的用武之地。你可以在自己的桌面或云 IDE 提供的虚拟桌面上使用它,无论你在哪里开发代码。</p>
<p>在本模块中,你将熟悉并使用各种 Git 命令来克隆和分叉仓库,以及使用命令行提交、推送和拉取更改。</p>
<h2 id="21-git-工作流概览"><a class="markdownIt-Anchor" href="#21-git-工作流概览"></a> 2.1. Git 工作流概览</h2>
<p>想象一下,你加入了一个为电子商务平台开发功能的团队。你的任务是添加产品推荐功能。团队使用 Git 和 GitHub 进行版本控制和协作。您将如何与使用 Git 和 GitHub 的团队有效协作?清楚地了解 Git 工作流程能确保您有效地使用 Git 进行版本控制和协作。这些知识将帮助你避免代码冲突和无意中覆盖团队成员工作等问题。</p>
<p>第一步是克隆团队在 GitHub 上托管的仓库。克隆会在本地计算机上创建一个项目代码副本,以及远程仓库的完整版本历史。通过克隆过程中建立的连接,你可以向远程仓库推送代码变更。你也可以将远程仓库中的任何更改提取到本地仓库中并进行更新。</p>
<p>作为开发人员,您可能会尝试多种方法来编写该功能的代码。在代码准备就绪之前,您可能不想让更改影响主分支。好的做法是从主分支创建一个分支,然后在新创建的分支上工作。在 Git 中,分支是一个基于主分支的独立开发空间,您可以在其中进行修改。在这种情况下,添加功能时不能干扰主代码库。</p>
<p>开发完功能后,下一步就是选择修改过的文件并将它们移到暂存区(Staging area)。暂存区是一个临时存储空间,在要求 Git 将所选文件保存到本地仓库之前,您可以在这里收集这些文件。现在您可以将文件提交到新创建的分支。提交文件可以记录更改,确保新功能成为分支的一部分。当你提交文件时,包含提交信息可为你和团队成员提供上下文,以便他们理解变更。例如,在提交信息中加入「已实现产品推荐功能」。</p>
<p>下一步是将分支中的变更推送到远程仓库。通常情况下,代码在合并到远程仓库的主分支之前,会由负责管理仓库的维护者进行审核。要合并分支,需要创建拉取请求。这是向维护者提出的请求,请其审查并批准分支中的更改。维护者合并拉取请求后,分支中的更改就会反映在主分支中。同样,如果你有维护者权限,就会收到团队成员的拉取请求,你将审查并批准他们的请求。</p>
<p>您已经了解了软件开发项目的典型工作流程。在某些情况下,你可能会从头开始一个项目,并打算与他人合作。你可以将本地项目目录初始化为 Git 仓库,这样 Git 就会开始跟踪项目目录中的改动。下一步是选择所有需要 Git 跟踪的项目文件,将它们移到暂存区,然后进行初始提交。接着创建一个空白仓库,并将本地 Git 仓库链接到远程仓库。再之后,你会把本地仓库中的所有项目文件推送到远程仓库。其他开发人员可以克隆远程仓库,并按照常规工作流程更新项目文件。</p>
<p>让我们通过一个用例来更好地理解工作流程。某公司为一个新的网络应用程序开发项目指派了一个由开发人员、测试人员和产品经理组成的团队。首席开发员 Anne 在自己的工作目录中初始化了一个 Git 仓库。她创建项目文件,将其移动到暂存区域,然后进行初始提交。然后,她将提交推送到自己创建的空白远程仓库。所有开发人员都克隆了远程仓库,并通过创建分支开始工作。</p>
<p>其中一名开发人员 John 负责实现用户身份验证功能。他从主分支中创建了一个名为 <code>User Auth</code> 的新分支。经过全面测试后,他将分支推送到远程仓库,并创建了一个拉取请求。Anne 审核并批准了拉取请求,将修改合并到主分支中,这样其他开发人员就可以访问 John 所做的修改。同样,其他开发人员也会向远程仓库推送他们所做功能的提交。至此,功能开发完成,项目准备发布。</p>
<p>Anne 从远程仓库中的主分支创建了一个名为 <code>Release 1.0</code> 的发布分支。团队从远程仓库中提取变更,以便更新本地仓库。他们在 <code>Release 1.0</code> 分支中执行最终测试、错误修复和文档更新。测试完成后,他们提交更改,将提交推送到远程仓库,并创建拉取请求。Anne 审核并将更改合并到主分支中,然后将发布标记为 <code>Release 1.0</code>。</p>
<h2 id="22-git-命令概述"><a class="markdownIt-Anchor" href="#22-git-命令概述"></a> 2.2. Git 命令概述</h2>
<p>Git 命令有多种用途,例如跟踪和保存更改,以及与他人共享更改。通常情况下,许多此类活动都是通过网页界面执行的。命令行界面(或 CLI)是执行这些活动的另一种选择。</p>
<p>让我们来学习一些基本命令,如:</p>
<ul>
<li><code>git init</code></li>
<li><code>git add</code></li>
<li><code>git status</code></li>
<li><code>git commit</code></li>
<li><code>git reset</code></li>
<li><code>git log</code></li>
<li><code>git branch</code></li>
<li><code>git checkout</code></li>
<li><code>git merge</code></li>
</ul>
<p><code>git init</code> 命令会在一个目录中初始化一个新的 Git 仓库,这是为项目设置版本控制的第一步。要创建一个 Git 仓库,可以在命令提示符下导航到所需的目录。然后运行 <code>git init</code> 命令。该命令将创建一个名为 <code>.git</code> 的隐藏子目录。</p>
<p>第二个命令是 <code>git status</code> 命令。通过 <code>git status</code>,您可以查看工作目录的状态以及您所做修改的暂存快照。它提供的信息包括哪些文件已被修改,以及这些文件是否为下一次提交而暂存。为此,您可以导航到 git 仓库所在的目录,然后在命令提示符下运行 <code>git status</code> 命令。这将显示有关当前仓库状态的信息。</p>
<p>第三种是 <code>git add .</code> 命令,它可以将工作目录中的改动移动到暂存区域。例如,您的 Git 仓库中有一个名为 <code>index.html</code> 的文件,您在其中做了一些改动。这些改动将包含在下一次提交中。为此,你可以打开命令提示符并导航到有 <code>index-html</code> 文件的 Git 仓库。运行 <code>git add .</code> 命令。这样,当前目录中的所有改动都会在下一次提交时加入。</p>
<p>第四个是 <code>git commit</code> 命令。<code>git commit</code> 会将您所做修改的阶段快照保存到项目中,并附带说明性信息。这条信息解释了提交的目的。假设您想在仓库中创建一个新的 HTML 文件。您可以使用 <code>git commit -m "commit message"</code> 命令来提供描述性信息,比如 <code>git commit -m "created a new HTML file"</code>。</p>
<p>至此,你已经了解了 <code>git init</code>、<code>git add</code>、<code>git status</code> 和 <code>git commit</code> 命令。</p>
<p>现在,第五个命令是 <code>git log</code> 命令,它能让你浏览项目以前的改动。如果想查看提交历史,可以定位到 Git 仓库所在的目录,然后运行 <code>git log</code> 命令。这将提供每次提交的相关信息。例如,创建一个新的 HTML 文件就会反映在提交历史中。</p>
<p>下一个命令是 <code>git reset</code>。<code>git reset</code> 命令会撤销您对工作目录中文件所做的更改。因此,如果代码出错,可以运行 <code>git reset</code> 命令。通过使用 <code>git reset soft</code> 命令,您将重新添加已暂存的更改,并准备好再次提交。</p>
<p>第七个命令是 <code>git branch</code> 命令。它可以列出、创建、重命名甚至删除 Git 仓库中的分支。例如,如果想在项目中创建一个名为 <code>code list</code> 的新分支,可以使用 <code>git branch</code> 命令,后面跟上新分支的名称,在本例中就是 <code>code_list</code>。</p>
<p>第八个命令是 <code>git checkout</code> 命令。<code>git checkout</code> 命令可以让你在现有分支之间切换。因此,如果你想切换到 Git 仓库中名为 <code>code_list</code> 的分支,可以运行 <code>git checkout</code> 命令,后面跟上该分支的名称,即 <code>code_list</code>。这条命令会从仓库中签出一个分支到工作目录中。</p>
<p>第九条也是最后一条命令是 <code>git merge</code>。<code>git merge</code> 可以让你把所有东西重新组合在一起,并将特性分支与主分支合并。因此,如果您在代码列表分支上实现了一个新功能,您就会想把它合并回主分支。您可以使用 <code>git checkout</code> 命令进入目标分支,然后使用 <code>git merge</code> 命令,后面跟上分支名称,在本例中就是 <code>code_list</code>。该命令允许 Git 将特性分支的所有变更集应用到主分支的顶端。</p>
<h4 id="221-更多的命令"><a class="markdownIt-Anchor" href="#221-更多的命令"></a> 2.2.1. 更多的命令</h4>
<ul>
<li><code>git pull</code>:它能从远程仓库获取变更,并将其合并到本地分支。首先,运行 <code>git checkout</code> 命令切换到要合并的分支。然后,运行 <code>git pull</code> 命令,它会从远程仓库的主分支获取改动,并将其合并到你的当前分支。</li>
<li><code>git push</code>:它能将本地仓库内容上传到远程仓库。首先运行 <code>git checkout</code> 命令,确保您所在的是要推送的分支,然后再将该分支推送到远程仓库。</li>
<li><code>git version</code>:它显示系统上安装的当前 Git 版本。</li>
<li><code>git diff</code>:它能显示提交之间的变化、提交树和工作树等。它还能比较分支。</li>
<li><code>git revert</code>:它通过应用新提交来恢复提交。这会创建一个新的提交,撤销上次提交所做的更改。</li>
<li><code>git config -global user.email <Your GitHub Email></code>:它为 Git 设置全局电子邮件配置。需要在提交前执行,以验证用户的电子邮件 ID。</li>
<li><code>git config –global user.name <Your GitHub Username></code>:它为 Git 设置全局用户名配置。需要在提交前执行,以验证用户的用户名。</li>
<li><code>git remote</code>:它列出了与本地仓库相关联的所有远程仓库的名称。
<ul>
<li><code>git remote -v</code>:它列出了本地 Git 仓库所连接的所有远程仓库,以及与这些远程仓库相关的 URL。</li>
</ul>
</li>
<li><code>git remote add origin <URL></code>:它使用指定的 URL 添加一个名为 <code>origin</code> 的远程仓库。</li>
<li><code>git remote rename</code>:在 <code>git remote rename</code> 命令后面跟上要重命名的远程仓库名称(在这个例子中,<code>origin</code>)和新名称(例如:<code>upstream</code>)。这将把 <code>origin</code> 远程仓库重命名为 <code>upstream</code>。</li>
<li><code>git remote rm <name></code>:它会删除指定名称的远程仓库。</li>
<li><code>git format-patch</code>:它可生成用于通过电子邮件提交的补丁。这些补丁可用于通过电子邮件提交更改或与他人共享。</li>
<li><code>git request-pull</code>:它能为电子邮件请求生成待处理更改摘要。它有助于将分支或分叉中的更改传达给上游仓库维护者。</li>
<li><code>git send-email</code>:它能以电子邮件的形式发送补丁集合。它允许你通过电子邮件向收件人发送多个补丁文件。请确保使用 <code>git config</code> 命令设置电子邮件地址和名称,以便电子邮件客户端在发送邮件时知道发件人的信息。</li>
<li><code>git am</code>:它将补丁应用到仓库。它将补丁文件作为输入,并将补丁文件中指定的更改应用到仓库。</li>
<li><code>git daemon</code>:它通过 <code>Git://</code> 协议公开软件仓库。Git 协议是一种轻量级协议,旨在实现 Git 客户端和服务器之间的高效通信。</li>
<li><code>git instaweb</code>:它能立即启动网络服务器来浏览资源库。它提供了一种简化的方式,无需配置完整的网络服务器,即可通过网络界面查看资源库内容。</li>
<li><code>git rerere</code>:它会重复使用之前已解决的合并冲突的解决记录。请注意,需要将 <code>rerere.enabled</code> 配置选项设为 <code>true</code>(<code>git config -global rerere.enabled true</code>),<code>git rerere</code> 才能工作。此外,请注意 <code>git rerere</code> 只适用于使用同一分支和提交解决的冲突。</li>
</ul>
<h1 id="3-最终项目"><a class="markdownIt-Anchor" href="#3-最终项目"></a> 3. 最终项目</h1>
<p>现在,你已经熟悉了 GitHub 仓库、分支和 Git 命令,在本模块中,你将运用所学知识和技能创建一个 GitHub 项目,添加一些文件(如开源许可证),并将其公开共享。</p>
<h2 id="31-概述和评分标准"><a class="markdownIt-Anchor" href="#31-概述和评分标准"></a> 3.1. 概述和评分标准</h2>
<p>现在您已经掌握了使用 GitHub UI 和 Git CLI 的知识和技能,您将利用这些技能在 Git 上创建一个开源项目,对该项目进行修改并将其提供给社区。您将分叉一个 GitHub 仓库,克隆该仓库到本地系统,更改本地仓库,在本地提交更改,推送回 GitHub 分叉仓库,并创建一个拉取请求,将您的更新添加到原始仓库。这个期末作业项目分为两个部分。</p>
<ol>
<li>
<p>GitHub UI</p>
<p>你最近受聘成为一家小额信贷初创公司的开发人员,该公司的使命是为低收入人群赋权并提供机会。核心团队目前使用 Subversion (SVN)管理代码。他们希望慢慢将代码转移到 Git。作为第一步,他们要求您在 GitHub 上的一个新仓库中托管计算单利的示例代码。您不仅要托管脚本,还要遵循本课程介绍的最佳实践,为开源项目创建支持文档,包括行为准则和贡献指南。此外,该资源库应根据 Apache License 2.0 向社区开放。</p>
</li>
<li>
<p>Git CLI</p>
<p>恭喜您与贵公司一起在 GitHub 上创建了一个开源的简单利息计算器 bash 脚本。您的更改已被接受和合并,公司已创建了一个新的全球资源库,供团队协作使用。随着时间的推移,其他开发人员也为该仓库做出了贡献。您的团队在其中一个标记文件中发现了一个错误。我们要求您 fork 这个仓库,在提供的实验室环境中使用 Git CLI 修正错误,并打开一个拉取请求。</p>
</li>
</ol>
<h2 id="32-第-1-部分-github-ui"><a class="markdownIt-Anchor" href="#32-第-1-部分-github-ui"></a> 3.2. 第 1 部分 - GitHub UI</h2>
<p>完成本实验后,你将证明自己可以:</p>
<ul>
<li>在 GitHub 账户中创建一个新仓库。</li>
<li>为项目选择合适的许可证。</li>
<li>创建一个 <code>README.md</code> 文件,解释项目的目的。</li>
<li>创建 <code>Code of Conduct</code> Markdown 文件,说明你希望社区成员如何行为和互动。</li>
<li>创建 <code>Contribution Guidelines</code> Markdown 文件,告诉社区如何贡献。</li>
<li>将新文件提交到仓库。</li>
</ul>
<p>注意:在整个实验过程中,系统会提示你将 URL 复制并粘贴到编辑器中,然后保存到自己的设备上。这些 URL 将在课程的 <code>Final Submission</code> 部分上传供同行评审。您可以使用任何编辑器应用程序来记录您的 URL。</p>
<h4 id="321-创建-github-仓库"><a class="markdownIt-Anchor" href="#321-创建-github-仓库"></a> 3.2.1. 创建 GitHub 仓库</h4>
<p>创建一个名为 <code>github-final-project</code> 的新 GitHub 仓库,并确保它是公开的。</p>
<p>选择 <code>Add a README file</code> 和 <code>Choose a license</code> 复选框。从下拉菜单中选择 <code>Apache 2.0 License</code>。</p>
<p><img src="/posts/369/1.png" alt=""></p>
<p>点击 <code>Create Repository</code>。您的仓库就创建完成了,其中包括 <code>README</code> 和 <code>LICENSE</code> 文件。现在,您可以更新仓库文件,为社区提供有用的信息。</p>
<p>将仓库的 URL 保存在记事本中,稍后提交给同行评审。</p>
<h4 id="322-更新-readme-文件"><a class="markdownIt-Anchor" href="#322-更新-readme-文件"></a> 3.2.2. 更新 <code>README</code> 文件</h4>
<p>在文件中添加以下信息:</p>
<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">A calculator that calculates simple interest given principal, annual rate of interest and time period in years.</span><br><span class="line"></span><br><span class="line">Input:</span><br><span class="line"> p, principal amount</span><br><span class="line"> t, time period in years</span><br><span class="line"> r, annual rate of interest</span><br><span class="line">Output</span><br><span class="line"> simple interest = p<span class="emphasis">*t*</span>r</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>可选:您可以在开发项目的过程中继续更新 <code>README</code> 文件。您可以从以下资源中找到一些有用的 <code>README</code> 内容:</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes">GitHub README</a></li>
<li><a target="_blank" rel="noopener" href="https://makeareadme.com/">Make a README</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/matiassingers/awesome-readme">Awesome README</a></li>
</ul>
</blockquote>
<h4 id="323-添加行为准则"><a class="markdownIt-Anchor" href="#323-添加行为准则"></a> 3.2.3. 添加行为准则</h4>
<p>行为准则有助于为项目参与者的行为制定基本规则。它定义了如何参与社区活动的标准。</p>
<p>GitHub 提供了常用的行为准则模板,可帮助您快速为项目添加行为准则。要在项目中添加行为准则,请完成以下步骤:</p>
<ol>
<li>在仓库根目录下添加一个名为 <code>CODE_OF_CONDUCT.md</code>、模板为 <code>Contributor Covenant</code> 的新文件。</li>
<li>访问仓库主页,检查文件是否已创建。</li>
</ol>
<p><img src="/posts/369/2.png" alt="img.png"></p>
<p>输入 <code>CODE_OF_CONDUCT</code> 后就会自动出现选择模板的选择。</p>
<h4 id="324-增加贡献指南"><a class="markdownIt-Anchor" href="#324-增加贡献指南"></a> 3.2.4. 增加贡献指南</h4>
<p>贡献指南告诉项目参与者如何为项目做出贡献。要添加贡献指南,请完成以下步骤:</p>
<ol>
<li>
<p>在仓库根目录下创建一个名为 <code>CONTRIBUTING.md</code> 的新文件,其中包含以下信息:</p>
<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">All contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas are welcome.</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>
<p>将文件提交到主分支,并检查它是否列在仓库的主页上。</p>
</li>
</ol>
<blockquote>
<p>您也可以选择查看以下指南,了解贡献指南的示例并更新此文件:</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://github.com/Call-for-Code-for-Racial-Justice/Legit-Info/blob/main/CONTRIBUTING.md">Contributing to Legit Info, a Call for Code for Racial Justice Project</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/openeew/openeew/blob/master/CONTRIBUTING.md">Contributing to OpenEEW</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/atom/atom/blob/master/CONTRIBUTING.md">Contributing to Atom</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/rails/rails/blob/main/CONTRIBUTING.md">How to contribute to Ruby on Rails</a></li>
</ul>
</blockquote>
<h4 id="325-托管脚本文件"><a class="markdownIt-Anchor" href="#325-托管脚本文件"></a> 3.2.5. 托管脚本文件</h4>
<ol>
<li>在仓库根目录下新建一个名为 <code>simple-interest.sh</code> 的文件。</li>
<li>在新文件中添加以下代码:<figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># This script calculates simple interest given principal,</span></span><br><span class="line"><span class="comment"># annual rate of interest and time period in years.</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Do not use this in production. Sample purpose only.</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Author: Upkar Lidder (IBM)</span></span><br><span class="line"><span class="comment"># Additional Authors:</span></span><br><span class="line"><span class="comment"># <your GitHub username></span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Input:</span></span><br><span class="line"><span class="comment"># p, principal amount</span></span><br><span class="line"><span class="comment"># t, time period in years</span></span><br><span class="line"><span class="comment"># r, annual rate of interest</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Output:</span></span><br><span class="line"><span class="comment"># simple interest = p*t*r</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Enter the principal:"</span></span><br><span class="line"><span class="built_in">read</span> p</span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Enter rate of interest per year:"</span></span><br><span class="line"><span class="built_in">read</span> r</span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Enter time period in years:"</span></span><br><span class="line"><span class="built_in">read</span> t</span><br><span class="line"></span><br><span class="line">s=`<span class="built_in">expr</span> <span class="variable">$p</span> \* <span class="variable">$t</span> \* <span class="variable">$r</span> / 100`</span><br><span class="line"><span class="built_in">echo</span> <span class="string">"The simple interest is: "</span></span><br><span class="line"><span class="built_in">echo</span> <span class="variable">$s</span></span><br></pre></td></tr></tbody></table></figure>
</li>
<li>将文件提交到主分支。</li>
</ol>
<h2 id="33-第-2-部分-git-cli"><a class="markdownIt-Anchor" href="#33-第-2-部分-git-cli"></a> 3.3. 第 2 部分 - Git CLI</h2>
<p>完成本实验后,您将能够证明自己可以:</p>
<ul>
<li>将上游仓库 fork 到自己的账户。</li>
<li>本地克隆代码。</li>
<li>在仓库中创建一个分支。</li>
<li>在分支中进行修改并提交。</li>
<li>将分支合并回主分支。</li>
<li>从分叉仓库向上游仓库创建拉取请求。</li>
<li>还原之前所做的更改。</li>
</ul>
<h4 id="331-fork-仓库"><a class="markdownIt-Anchor" href="#331-fork-仓库"></a> 3.3.1. Fork 仓库</h4>
<p>Fork 项目的 <a target="_blank" rel="noopener" href="https://github.com/ibm-developer-skills-network/jbbmo-Introduction-to-Git-and-GitHub">源代码库</a>。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/ibm-developer-skills-network/jbbmo-Introduction-to-Git-and-GitHub"><img src="https://gh-card.dev/repos/ibm-developer-skills-network/jbbmo-Introduction-to-Git-and-GitHub.svg" alt="ibm-developer-skills-network/jbbmo-Introduction-to-Git-and-GitHub - GitHub"></a></p>
<h4 id="332-修正错字并与-master-合并"><a class="markdownIt-Anchor" href="#332-修正错字并与-master-合并"></a> 3.3.2. 修正错字并与 <code>master</code> 合并</h4>
<div class="danger">
<p>我自己在本地环境使用 Git Bash,分支并非教程中写的 <code>main</code> 而是 <code>master</code>,因此下面的内容都会以 <code>master</code> 分支为主。</p>
</div>
<ol>
<li>克隆自己 Fork 的仓库。<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/<Your name>/jbbmo-Introduction-to-Git-and-GitHub.git</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>创建一个名为 <code>bug-fix-typo</code> 的分支。<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout -b bug-fix-typo</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>将 <code>README.md</code> 中的页脚从<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2022 XYZ, Inc.</span><br></pre></td></tr></tbody></table></figure>
改为<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2023 XYZ, Inc.</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>添加修正后的文件并提交,同时写上有意义的信息。<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git add README.md</span><br><span class="line">git commit -m <span class="string">"Updated the footer year in README.md"</span></span><br></pre></td></tr></tbody></table></figure>
</li>
<li>将修复推送到 <code>bug-fix-typo</code> 分支。<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin bug-fix-typo</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>切换到 <code>master</code> 分支。将 <code>bug-fix-typo</code> 分支合并回 <code>master</code> 分支。<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout master</span><br><span class="line">git merge bug-fix-typo</span><br></pre></td></tr></tbody></table></figure>
</li>
</ol>
<h4 id="333-还原错字并提交拉取请求"><a class="markdownIt-Anchor" href="#333-还原错字并提交拉取请求"></a> 3.3.3. 还原错字并提交拉取请求</h4>
<ol>
<li>
<p>检查 <code>master</code> 分支中 <code>README.md</code> 的内容。该文件现在应为:</p>
<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2023 XYZ, Inc.</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>可以在 Git Bash 中使用 <code>cat <filename></code> 命令来直接查看。</p>
</blockquote>
</li>
<li>
<p>创建一个名为 <code>bug-fix-revert</code> 的新分支。</p>
</li>
<li>
<p>使用 <code>git revert</code> 命令还原上一个任务中的更改。</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">log</span></span><br><span class="line">git revert <commit-hash></span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>首先,您需要找到要恢复的变更的提交哈希值。这可以通过 <code>git log</code> 查看提交历史来实现。有了提交哈希值,就可以用 <code>git revert <commit-hash></code> 来还原了。记得将 <code><commit-hash></code> 替换为实际的提交哈希值。</p>
</blockquote>
<p>现在文件应为:</p>
<figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2022 XYZ, Inc.</span><br></pre></td></tr></tbody></table></figure>
</li>
<li>
<p>将还原推送到你的仓库中的 <code>bug-fix-revert</code> 分支。</p>
</li>
<li>
<p>转到 GitHub UI。从你的仓库的 <code>bug-fix-revert</code> 分支向原始仓库的主分支创建一个新的拉取请求。此 PR 将自动关闭。</p>
</li>
</ol>
<p><img src="/posts/369/3.png" alt="img.png"></p>
<h4 id="334-检查分支状态"><a class="markdownIt-Anchor" href="#334-检查分支状态"></a> 3.3.4. 检查分支状态</h4>
<p>导航至页面上 GitHub UI 中的 <code>Branches</code> 部分。它的格式如下:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/<Your Github username>/jbbmo-Introduction-to-Git-and-GitHub/branches</span><br></pre></td></tr></tbody></table></figure>
<p>在这一部分中,您可以找到分支名称及其当前状态。</p>
</body></html></div></article></div></main><footer><div class="paginator"><a class="prev" href="75ba.html">上一篇</a><a class="next" href="fa4d.html">下一篇</a></div><!-- Webmention 显示区域--><div class="webmention-section webmention-empty" data-page-url="posts/369.html" data-full-url="https://cytrogen.icu/posts/369.html" data-mode="static">
<h3 class="webmention-title">Webmentions (<span class="webmention-count">0</span>)</h3>
<div class="webmention-list"></div>
<span>暂无 Webmentions</span>
</div><div class="copyright"><p class="footer-links"><a href="../friends/index.html">友链</a><span class="footer-separator"> ·</span><a href="../links/index.html">邻邦</a><span class="footer-separator"> ·</span><a href="../contact/index.html">联络</a><span class="footer-separator"> ·</span><a href="../colophon/index.html">营造记</a><span class="footer-separator"> ·</span><a href="../atom.xml">RSS订阅</a></p><p>© 2025 - 2026 <a href="https://cytrogen.icu">Cytrogen</a>, powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/cytrogen/hexo-theme-ares" target="_blank">hexo-theme-ares</a>.</p><p><a href="https://blogscn.fun" target="_blank" rel="noopener">BLOGS·CN</a></p></div></footer></div></div><a class="back-to-top" href="#top" aria-label="返回顶部"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M3.293 9.707a1 1 0 010-1.414L9.586 2a2 2 0 012.828 0l6.293 6.293a1 1 0 01-1.414 1.414L11 3.414V17a1 1 0 11-2 0V3.414L2.707 9.707a1 1 0 01-1.414 0z"></path></svg></a><script>document.addEventListener('DOMContentLoaded', function() {
const codeBlocks = document.querySelectorAll('figure.highlight');
codeBlocks.forEach(block => {
let caption = block.querySelector('figcaption');
if (!caption) {
caption = document.createElement('figcaption');
block.insertBefore(caption, block.firstChild);
}
const info = document.createElement('div');
info.className = 'info';
const filename = caption.querySelector('span');
if (filename) {
filename.className = 'filename';
info.appendChild(filename);
}
const lang = block.className.split(' ')[1];
if (lang) {
const langSpan = document.createElement('span');
langSpan.className = 'lang-name';
langSpan.textContent = lang;
info.appendChild(langSpan);
}
const sourceLink = caption.querySelector('a');
if (sourceLink) {
sourceLink.className = 'source-link';
info.appendChild(sourceLink);
}
const actions = document.createElement('div');
actions.className = 'actions';
const codeHeight = block.scrollHeight;
const threshold = 300;
if (codeHeight > threshold) {
block.classList.add('folded');
const toggleBtn = document.createElement('button');
toggleBtn.textContent = '展开';
toggleBtn.addEventListener('click', () => {
block.classList.toggle('folded');
toggleBtn.textContent = block.classList.contains('folded') ? '展开' : '折叠';
});
actions.appendChild(toggleBtn);
}
const copyBtn = document.createElement('button');
copyBtn.textContent = '复制';
copyBtn.addEventListener('click', async () => {
const codeLines = block.querySelectorAll('.code .line');
const code = Array.from(codeLines)
.map(line => line.textContent)
.join('\n')
.replace(/\n\n/g, '\n');
try {
await navigator.clipboard.writeText(code);
copyBtn.textContent = '已复制';
copyBtn.classList.add('copied');
setTimeout(() => {
copyBtn.textContent = '复制';
copyBtn.classList.remove('copied');
}, 3000);
} catch (err) {
console.error('复制失败:', err);
copyBtn.textContent = '复制失败';
setTimeout(() => {
copyBtn.textContent = '复制';
}, 3000);
}
});
actions.appendChild(copyBtn);
caption.innerHTML = '';
caption.appendChild(info);
caption.appendChild(actions);
const markedLines = block.getAttribute('data-marked-lines');
if (markedLines) {
const lines = markedLines.split(',');
lines.forEach(range => {
if (range.includes('-')) {
const [start, end] = range.split('-').map(Number);
for (let i = start; i <= end; i++) {
const line = block.querySelector(`.line-${i}`);
if (line) line.classList.add('marked');
}
} else {
const line = block.querySelector(`.line-${range}`);
if (line) line.classList.add('marked');
}
});
}
});
});</script><script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script><script>(function() {
document.addEventListener('DOMContentLoaded', function() {
const themeToggle = document.querySelector('.theme-toggle');
if (!themeToggle) return;
const getCurrentTheme = () => {
return document.documentElement.getAttribute('data-theme') || 'light';
};
const updateUI = (theme) => {
const isDark = theme === 'dark';
themeToggle.setAttribute('aria-pressed', isDark.toString());
};
const setTheme = (theme) => {
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
const pageWrapper = document.getElementById('page-wrapper');
if (pageWrapper) {
pageWrapper.setAttribute('data-theme', theme);
}
// Find and remove the temporary anti-flicker style tag if it exists.
// This ensures the main stylesheet takes full control after the initial load.
const antiFlickerStyle = document.getElementById('anti-flicker-style');
if (antiFlickerStyle) {
antiFlickerStyle.remove();
}
localStorage.setItem('theme', theme);
updateUI(theme);
};
const toggleTheme = () => {
const current = getCurrentTheme();
const newTheme = current === 'light' ? 'dark' : 'light';
setTheme(newTheme);
};
updateUI(getCurrentTheme());
themeToggle.addEventListener('click', toggleTheme);
if (window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', function(e) {
if (!localStorage.getItem('theme')) {
const theme = e.matches ? 'dark' : 'light';
setTheme(theme);
}
});
}
});
})();
</script><script src="../js/details-toggle.js" defer></script><script>(function() {
document.addEventListener('DOMContentLoaded', function() {
const backToTopBtn = document.querySelector('.back-to-top');
if (!backToTopBtn) return;
const toggleButtonVisibility = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const shouldShow = scrollTop > 200;
if (shouldShow) {
backToTopBtn.classList.add('is-visible');
} else {
backToTopBtn.classList.remove('is-visible');
}
};
let ticking = false;
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
toggleButtonVisibility();
ticking = false;
});
ticking = true;
}
};
const scrollToTop = (event) => {
event.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
window.addEventListener('scroll', handleScroll);
backToTopBtn.addEventListener('click', scrollToTop);
toggleButtonVisibility();
});
})();</script></body></html>