使用 Git 在 GitHub 上托管代码

浅蓝喜灰

本文将简要介绍一些基础的 Git 操作,帮助你学习 Git 的基本使用,同时会介绍一些基本的命令行窗口操作,最后会介绍如何在一些较为流行的文本编辑器和 IDE 上进行 Git 操作。
在开始本教程之前,请先安装好 Git,如果你使用的平台是 Windows,你可以阅读站内文章 Git for Windows 安装指南来安装 Git。同时,本文使用 GitHub 作为代码托管平台,因此你还需要拥有一个 GitHub 账号和能够稳定访问 GitHub 的平台。确保满足上述条件以后,你可以继续往下阅读。

创建远程仓库

你需要在 GitHub 上创建一个空仓库,请在 GitHub 个人主页面板 上的左上角找到下图的New按钮。

点击该按钮,你将会得到一个类似下图的新界面,我将逐项给你解释。

  • Repository name
    指定仓库的名字,后续不能更改。当你输入名字后,GitHub 会自动检查你的仓库名字是否有效,并告知你当前名字是否能够使用。
    请注意,仓库名字不支持中文以及绝大多数标点符号和特殊字符,因此任何不符合要求的字符都会自动用减号代替。
    由于你的仓库名字将会成为该仓库链接的一部分,所以,使用简洁明了的仓库名字会更好。

  • Description (optional)
    指定仓库的描述,可以后续更改。你可以在这里使用中文。
    需要注意的是,请不要在这里写下长篇大论,仓库的描述也应当简洁明了,如果你想充分介绍仓库的内容,请写在仓库根目录下的 README.md 里面。
    你也可以什么都不写,但别人将无法在进入你的仓库之前了解你的项目是做什么的。

  • Public / Private
    仓库可见性,可以后续更改。
    选择 Public 将意味着你的仓库对大众可见,而 Private 则意味着仓库只对指定的用户可见。根据你的需求选择即可,如果你只是想跟着本文学习一下使用,则选择两者皆可。

  • Add a README file
    自动在仓库根目录创建 README.md 文件,可以后续自己创建和删除该文件。

    提示

    你需要勾选该选项,我们需要用此制造文件冲突,方便后续介绍处理冲突的方法。

  • Choose a License
    为仓库指定开源许可证,可以后续更改。
    如果你不了解,先选择 None。

    提示

    如果你选定了协议,则会自动在仓库内创建文件,可能造成的后果如 README 小节一样。

  • Create repository
    点击 Create repository 即可创建仓库。

Git 配置

用户名与邮箱

尽管 Git for Windows 的安装程序为你完成了许多的配置,你还是需要自行完成用户名和邮箱地址的配置。通过输入下列命令

1
2
git config --global user.name "你使用的用户名"
git config --global user.email "你使用的邮箱"

你就会将名字和邮箱都更改为双引号之内的内容,每次提交时,这些信息将会一并写入到记录中。参数 –global 意味着这一信息将应用到所有仓库的所有提交,这样一来,每次创建一个新的本地仓库时,你就不需要重新指定这些信息。

提示

如果你想要为某一特定仓库指定这些信息时,请先打开到该仓库根目录下,然后执行命令

1
2
git config user.name "局部仓库使用的名字"
git config user.email "局部仓库使用的邮箱"

这样一来,仓库的局部设置就会与全局设置区分开来,互不干扰。

这两个配置选项是为了在提交更改时供他人进行溯源,当他人看到你的提交,希望与你沟通时,可以通过此项配置来联系上你。
然而,这些配置是“仅供参考”的,它不作为验证个人身份的唯一依据,你也可以随时更改,虽说大多数平台如 GitHub 都在弱化这俩配置的存在感,但正确配置这些信息,也不失为一个好主意。

提示

你不需要设定这些信息使其与 GitHub 或者其他代码托管平台上的个人信息一致。

默认文本编辑器

你可以在 Git for Windows 安装程序中设定,也可以选择在命令行中设定。假若你希望更改默认文本编辑器,比如你先前选择使用记事本作为文本编辑器,而现在你希望更换为 Visual Studio Code,那么你可以通过输入命令

1
git config --global core.editor "C:/Program Files/Microsoft VS Code/Code.exe" --wait

将其更换为 Visual Studio Code,其中双引号内的文件路径是 Visual Studio Code 的文件路径,参数 –wait 意味着通过 Git 启动 Visual Studio Code 之后,必须等待 VSCode 被关闭才能继续执行后续命令。如果你希望更换为其他文本编辑器,请确保输入的路径是指向 exe 文件的完整路径,可以参考上方的路径来写。

配置认证

先前我们提到 user.name 和 user.email 不是身份认证的依据,那么 Git 总得有什么方式去认证身份,否则就乱套了,比较常用的认证方式,有 HTTPS 和 SSH 两种模式,这两种认证模式比较常用,因此你需要学习如何使用。

HTTPS

在 GitHub 创建 个人访问密钥

请前往 GitHub 创建 PAT。
在 Dashboard 页面,点开侧边栏,然后选择 Settings 选项。

点开后在左边栏往下滑找到 Developer settings 并点击。

点开后在左侧边栏找到 Personal access tokens 并在展开后的子菜单列表中找到 Fine-grained tokens,将其点开。

在右侧菜单中点击 Generate new token 按钮。

在新界面中,按照介绍进行如下配置。


  • Token name
    密钥名字,没有特殊起名要求。
  • Expiration
    密钥过期时间,最长为一年,密钥一旦过期就需要重新生成。
  • Description
    密钥介绍,非必填项。
  • Resource owner
    密钥属主,请确保属主为你自己,而不是隶属于任何组织或其他个人,否则将可能导致密钥无法访问你的仓库。
  • Repository access
    可访问的仓库。
    • Public Repositories (read-only)
      通过该密钥,只可以访问可见性为公共的仓库,并且只拥有读取权限。
    • All repositories
      通过该密钥,可以访问你的所有仓库(不论是已创建或者是以后创建的),并且拥有所分配到的权限。
    • Only select repositories
      通过该密钥,只可以访问你限定的仓库(显然,必须是已经创建的仓库),并且拥有所分配到的权限。最多可以分配 50 个仓库。
  • Permissions
    密钥权限。
    • Repository permissions
      仓库权限。
      • Content
        访问范围包括仓库文件等等,要想推送文件更改,需要获得此权限,我们只需要将该设定修改为 Read and write 即可。
        • No access
          该密钥不具有此项设定的任何权限。
        • Read-only
          该密钥只有此项设定的读取权限。
        • Read and write
          该密钥拥有此项设定的读和写权限。

提示

如此细致的权限分类实际上是确保密钥使用者只能访问他们必须访问的内容,过于粗略的权限分类,可能会让你在授予用户 A 权限的同时,不得不附带授予 B 权限,导致用户拥有本不该拥有的权限。

选择完你所需要的权限后,滚动到页面最底下,可以找到 Generate token 按钮。

点击后即可生成密钥,在新页面即可点击密钥右边的按钮进行复制。

警告

你的密钥内容只会出现一次,一旦刷新或者关闭页面就不会再次显示!

在 Windows 上配置密钥

在 Windows 开始菜单中搜索凭据管理器

或沿控制面板——用户账户——凭据管理器打开,在凭据管理器界面选中找到普通凭据,点击添加普通凭据

按照下图填写地址、用户名和密码。

  • Internet 地址或网络地址
    填写 git:https://github.com
  • 用户名
    填写你在 GitHub 登录时要输入的用户名。
  • 密码
    填写你在 GitHub 上创建 PAT 时复制的密钥内容。
    点击确定保存,配置完成。

SSH

提示

打开 PowerShell 并执行下列命令。

1
cat ~/.ssh/id_rsa.pub

这将直接获取你的 SSH 公钥。如果收到提示说“该路径不存在”,请按照提示执行下列内容。如果你的 PowerShell 没有报错,而是给出了一段密钥,那么你就获得了你的 SSH 公钥,请完整复制,并直接跳至“在 GitHub 上配置 SSH 密钥”部分。

生成 SSH 密钥对

在 PowerShell 执行命令。

1
ssh-keygen -t rsa -b 4096 -C "example@mail.com"

其中,-t 参数紧跟 rsa,代表所采用的密钥类型,-b 代表密钥长度,最小 768 位,最大 4096 位,-C 则为该密钥的注释,你可以写上你的邮箱,也可以写别的。

提示

提示 ssh-keygen 无法被识别为命令?
请打开 Git 的安装目录,打开文件夹 usr 后接着打开 bin 文件夹,复制当前目录的路径,将该路径添加到系统环境变量(如果你安装 Git 的时候,没有修改它的安装路径,那么它应该是 C:/Program Files/Git/usr/bin),添加到系统环境变量后即可使用。

输入 ssh-keygen 命令后,会创建文件用于存储密钥,你需要指定这些新文件的名字,默认是 id_rsa

1
2
# 如果直接按回车,不输入任何内容,则起名为 id_rsa
Enter file in which to save the key (example/.ssh/id_rsa):

接着要求输入口令,你可以选择不使用任何口令,但仍然建议你输入。

1
2
3
4
# 如果直接按回车,不输入任何内容,则不会要求输入口令验证
Enter passphrase (empty for no passphrase):
# 二次核对口令(上一步骤如果没有输入任何内容的话请直接按回车跳过)
Enter same passphrase again:

完成以后,假若你收到提示告诉你密钥已经保存在某个文件下,则生成成功。

1
Your identification has been saved in /c/Users/you/.ssh/id_rsa.

在 GitHub 上配置 SSH 密钥

打开 GitHub,然后选择 Settings 选项。

在左侧边栏中选择 SSH and GPG keys 选项。

选择 New SSH key 选项。

填写密钥标题、类型和 id_rsa 中的内容。

  • Title
    起一个密钥标题,当你有多个密钥时,你可以凭借标题来区分密钥对应的主机。
  • Key type
    密钥类型,选择 Authentication key 即可。
  • Key
    密钥内容。你需要粘贴来自 id_rsa.pub 中的内容,下面是一个快速的拷贝方法。
    CMD 中执行
    1
    clip < %USERPROFILE%/.ssh/id_rsa.pub
    将 SSH 密钥对的公钥复制到剪贴板,如果没有提示如“找不到文件”之类的错误,则你已成功拷贝公钥,将其粘贴到此栏即可。

    提示

    如果你被告知诸如“‘<’运算符是为将来使用而保留的。”“找不到路径‘C:/Users/%USERPROFILE%’,因为该路径不存在。”之类的错误,那么这意味着你是在 PowerShell 中运行的命令,请注意我先前强调的是在 CMD 中执行命令,这两个是不同的终端,请不要混淆使用。
    因此请先切换到 CMD 窗口,然后重新执行一遍刚刚的命令即可。

为 SSH 密钥正确填写各键值之后,点击 Add SSH key 按钮,即可保存于 GitHub 上。密钥配置部分到此为止。

创建本地仓库

在你的电脑上新建一个文件夹用于存储仓库内的文件,文件夹名字不需要与你在 GitHub 上设定的仓库名相同,因此你可以给他起一个比较简单的名字。
为了方便说明,此处创建文件夹的操作是在 PowerShell 命令行窗口中完成的。

1
2
mkdir testdir
cd testdir

执行上述操作将会让你创建一个名为 testdir 的文件夹并打开,你可以选择先写点什么东西,也可以选择先初始化仓库,我们先选择初始化仓库,然后再添加文件,两者的顺序一般是可以调换的,因此你无需纠结是先初始化仓库还是先写文件。

1
git init

你可能会收到提示如下

这意味着你已经成功初始化了仓库,现在你可以往仓库内添加文件,但在此之前我们需要你做一些事情。

创建与修改文件

在你的仓库内新建一个 README.md 文件,使用记事本或者其他文本编辑器打开它,尝试拷贝下方代码块内的全部内容到该文件里面,或者你也可以写点别的什么。

1
2
# 这是一个测试仓库的 README 文件
请把这一整个代码块的内容都拷贝。

然后保存,接着我们再创建一个新的文件,就叫 NewFile.md,并将下列代码块的内容全部拷贝进该文件里面。

1
2
# 这是一个测试仓库的 Markdown 文件
请把这一整个代码块的内容都拷贝。

现在,我们创建了 2 个文件,但你必须先告诉 Git 有哪些文件发生了更改并且需要将更改应用到远程平台。

保存文件更改

输入命令

1
2
git add README.md
git add NewFile.md

此时你便成功添加 README.md 和 NewFile.md 两个文件到暂存区里面,但这时你还不可以直接推送到远程仓库,首先你要做的是将其提交到本地仓库。

提交到本地仓库

输入命令

1
git commit -m "改动说明"

此时将会把暂存区里面的内容提交到本地仓库,并附加一段说明,其中附带的参数 -m 使得你不必打开一个新的文本编辑器就可以把改动说明写下来;紧接着,你需要在 “改动说明” 一栏中写明白你做出的更改是什么,你可以随便写点,但说明应当简洁明了,不要啰嗦。

提示

当你参与到公共仓库的编辑中时,请务必将你的改动说明写明白,否则他人可能不会采用你的改动。

提交到远程仓库

将改动提交到本地仓库以后,你便可以将本地仓库推送到远程仓库,但此时我们尚且没有添加远程仓库到本地。
打开你在 GitHub 上的仓库页面。
点击 <> Code 按钮,然后确保选中 Local 选项卡,在 HTTPS 和 SSH 中任选其一,点击拷贝按钮,将链接拷贝下来。

PowerShell 中,将目录切换至仓库目录,如下图。

接着添加远端仓库,执行命令

1
git remote add origin 先前拷贝的仓库链接

即可添加别名为 origin 的远端仓库链接,你可以将 origin 改为其他名字。

提示

推送时,你无需考虑链接究竟是 HTTPS 还是 SSH,Git 将会自动根据链接来判断采用 SSH 推送还是采用 HTTPS 推送。

一旦完成,我们就可以接着进行推送。在上一步中我们已经提交修改到本地仓库,只差推送,接着执行

1
git push origin main

应当就可以完成推送了。

无法获取凭据

然而,你可能会被告知

1
fatal: unable to access 'https://github.com/1012796366/tutorial_repo.git/': SSL certificate problem: unable to get local issuer certificate

这意味着无法获取到本地 SSL 证书,这可能是因为你使用的是 OpenSSL 作为凭据验证方式,回想我们先前配置 HTTPS 时,我们并没有将 PAT 添加到 OpenSSL 指定的凭据文件里面,而是将 PAT 存储在 Windows 凭据管理器里面,因此 OpenSSL 必然无法访问到我们的 PAT。
一个简单的方法是,使用 Windows 凭据管理器来作为凭据验证方式,执行下列命令完成更换

1
git config --global http.sslbackend schannel

然后再执行一遍 git push,就没有无法访问 SSL 证书的问题了。

无法合并提交历史不同的仓库

然而一波刚平,一波又起,我们又有新的问题:

根据描述,Git 要求我们在下一次推送之前,先执行 git pull,然而,如果照做的话,就会提示

根据描述,我们在 git pull 时,由于远端仓库和本地仓库均有不同的提交(尽管远端和本地都有创建 README.md 的历史,但是两者创建的时间和内容均不一样),导致 Git 认为是两个仓库是独立不同的版本,拒绝合并,我们可以通过

1
git pull origin main --allow-unrelated-histories

来合并两个提交历史不一样的仓库。

无法自动合并的冲突文件

但是又有新的问题,被告知了文件冲突

根据描述,在执行 git pull 时,发生了文件冲突,而 Git 无法自动合并文件,需要我们自行手动修改。
你可能一头雾水,下面是一个相似的场景。
有一个仓库名为 repo,其下有分支 main,现有两个程序员 A 和 B 希望对其做出修改,他们是这么做的:

  • 程序员 A 在 main 分支上修改了 README.md
  • 程序员 B 从 main 分支分出了一个新的分支,名为 mod,并在此分支上修改了 README.md

如果尝试合并 A 和 B 两人的提交,就会发生文件冲突,并且不能自动合并
那么什么时候能够自动合并呢?下面是一个场景:

  • 程序员 A 在 main 分支上修改了 README.md
  • 程序员 B 从 main 分支分出了一个新的分支,名为 mod,但没有在此分支上修改 README.md

在此场景下,如果尝试合并 A 和 B 两人的提交,Git 就能自动合并,因为他们并没有对同一个文件做出修改。
一个形象的解释是,填志愿时,你妈妈列出的学校清单里,第一个就是某 211 的计算机专业,而你爸爸列出的学校清单里,第一个就是某 985 的机械专业,此时就出现了冲突,你必须自行设定采用哪一方的想法。
执行

1
git status

查看没有办法自动合并的文件都有哪些。

我们发现,README.md 是没有办法自动合并的文件,此时我们就需要自行决定该保留什么内容。
使用相应的编辑器(根据文件类型来决定)打开 README.md,我们可以发现内容变成了下图的样子。

<<<<<<< HEAD======= 之间的是我们本地的内容,而在 >>>>>>> 7b6b01fedb3c220fb303c9bcdc4e35516d59b3a9======= 之间的是远端仓库的内容。

提示

需要注意的是,>>>>>>> 7b6b01fedb3c220fb303c9bcdc4e35516d59b3a9 代表的是远端提交的 SHA 值,因人而异,而且,如果你是合并本地的两个分支时发生的冲突,则此处可能是另一个本地分支的名字而不是一串 SHA 值。

我们该怎么修改呢?实际上,你只需要记住一点,你在这里做出的任何修改,都会保存下来。
首先,删掉 <<<<<<< HEAD =======>>>>>>> 7b6b01fedb3c220fb303c9bcdc4e35516d59b3a9,如图。

接着,假设我们希望 README.md 里面的最终内容是这样的

1
2
# 这是一个测试仓库的 README 文件
请把这一整个代码块的内容都拷贝,作为演示仓库的一部分。

那么我们就直接修改文本为上面的内容就行了,如下图。

完成修改后,按下 Ctrl + S 保存文件,然后执行

1
git add README.md

将我们刚刚在 README.md 的修改保存到暂存区,接着提交到本地仓库

1
git commit -m "合并 README.md"

随后推送到远端

1
git push origin main

应当就成功推送了。执行效果如图

这时候我们在远端仓库中查看推送后的文件,就会发现它已经变成了我们先前编辑的样子(因为我本人提交的时候并没有完全按照文章中的示范来修改,所以这里稍有不同,请以你提交后的效果为准)。

其他补充

如果你在 git pull 或者 git merge 后想要放弃合并文件,执行

1
git merge --abort

可以终止并退出合并。


到这里你就已经学会了基本的 Git 使用,虽然我只是以 GitHub 作为示范,但是仍然可以适用于其他许多代码托管平台,如 Gitee 和 GitLab。
需要注意的是,本教程只涉及了 Git 和 GitHub 里极为基础的内容,受限于篇幅,关于 Pull Request、分支和其他更多的内容就不在此一一介绍了。

评论