Git概念以及仓库
Git是一个版本控制工具,可以将所有代码开发过程中的版本进行托管,可以形象地类比为代码存放的仓库。仓库分为两种,分别是本地仓库(Local Repository)和远端仓库(Remote Repository)。具体而言:
- 本地仓库即为存储在自己电脑上的一个版本管理仓库,对于进行了版本控制的文件夹而言,通常会在其子目录下存在一个.git文件以代表该文件夹进入了一个仓库
- 远程仓库则提供了代码备份,以及多人协作开发等功能。通过将代码上传到类似于Gitee,Github等远程仓库,可以实现代码的开源
Git有许多的命令,每一次执行git commit、git revert等命令时都会生成SHA编码,该编码在同一个仓库内是唯一的。
Git可以将涉及的区域分为四个部分,分别为工作区,暂存区,本地仓库,以及远程仓库。\(git\ add\) 负责将代码加入暂存区,\(git\ commit\)负责将代码加入到本地仓库,\(git\ push\)负责将代码推送到远端仓库。四部分关系具体示意图如下:
Git本地仓库中的基础命令
对于大部分的Git命令,若想对所有文件进行操作,一般形式为 git command .;若想对单个文件进行操作,一般形式为git command filename
git 的“增、删”
若想要为某个文件夹创建一个仓库,需要在对应的文件夹当中输入\(git\ init\)命令,此时文件夹内部会出现\(.git\)文件夹,视为仓库创建成功,具体如下:
创建仓库后,需要先将工作区的代码添加到暂存区,才能够将代码进行提交。将代码添加到暂存区的命令为\(git\ add\)。
Git最基本的命令是commit,翻译过来是提交,它负责将暂存区中的所有文件上传到本地仓库中。当Commit的次数足够多时,就会在一个分支下形成一个commit链。如上所述,每一次commit都会生成一个仓库内唯一的SHA编码,该编码则对应文件当前状态下的快照。编码也被称作为修订号,修订号具体示意图如下:
一个完整的修订号是一串很长的字符,如上图完整修订号为204c5970b47703b9573eccea27ef4084ae1bd3ac,框中的圈起的修订号为完整修订号的前七位,已经足够唯一表示一次修改。
commit 的完整写法为\(git\ \ commit -m \text{“content"}\),此外,在提交过程中有一套约定式提交(Conventional Commits),常见格式为:
<type>: <description>
其中,type为这次提交的类型,description为这次提交的描述。常见的类型分为如下几种:
| 类型 | 含义 |
|---|---|
| feat | 新增功能 |
| fix | 修复bug |
| docs | 只修改文档 |
| style | 不影响代码逻辑的风格式修改,如缩进、空格 |
| refactor | 对代码进行重构 |
| perf | 性能优化 |
| revert | 回滚提交 |
如,博客在某次修改中添加了一个音乐播放器,提交代码的命令应写成\(git\ \ commit\ \ -m\text{“feat: 新增音乐播放器”}\)。
Git在提交后有几种方法可以撤销,分为以下几种情况:
- 情况一:如果在工作区中改坏了某代码,但是该代码还未提交,使用\(git\ restore\)可以回退到最近的版本,或在IDE中点击discard将代码回退到最近的提交版本。
- 情况二: 如果在工作区中已经提交代码至暂存区,想要删除某个版本之后所有的修改,并将代码回退到该版本,可以使用\(git\ reset\ SHA\),该操作又可分为以下三种情况,每种情况均假设需要删除最近的版本:
| 情况 | 命令 | 效果 |
|---|---|---|
| 发现commit的信息写错了 | git reset –soft HEAD~1 | 只有commit被撤销,代码的修改还在且依然存放在暂存区 |
| 需要对代码进行重新修改 | git reset –mixed HEAD~1 | commit被撤销,代码被移除出暂存区,但是对其的修改还存在于工作区 |
| 完全舍弃该快照 | git reset –hard HEAD~1 | commit,工作区,代码的修改全部回退到指定的版本 |
git reset 有丢失代码的风险,故应该谨慎使用,尤其是在多人合作中更应谨慎!
- 情况三:如果工作区中已经提交代码至暂存区,发现之前某个版本的修改出现了问题,不再需要该版本的快照,但同时需要保留其它版本的快照,可以使用\(git \ revert\ SHA\),该操作被称作回滚提交,回滚提交的原理为:通过提交一个与需要回滚的快照完全相反的快照,以抵消上一次提交。
git diff
git diff 后按q可以退出该模式
要想比较不同文件、工作区域之间的差异,可以使用\(git\ diff\)命令,该命令分为以下几种情形,具体为:
| 需求 | 命令 |
|---|---|
| 查看所有未暂存的文件,即未git add的文件 | git diff |
| 查看当前工作区的代码和某一次提交的代码的区别 | git diff SHA – filename |
| 比较两个提交之间某个文件的区别 | git diff SHA1 SHA2 – filename |
| 只想看两次提交或者工作区和暂存区中哪些文件发生了变化 | git diff –name-only |
| 想查看不同分支中某文件的变化 | git diff 分支1 分支2 – filename |
如当前需要比较SHA分别为0daeq21和daqe14r的两次提交中QCPR.py文件的区别,可以使用命令: \[
git\ diff\ 0daeq21\ daqe14r\ -- QCPR.py
\] 
以该图为例,第一行代表正在对比两次提交的./idea/.gitignore文件,其中a代表旧版本,b代表新版本;第二行代表当前两次对比下来,新版本新增了一个文件,具体为./idea/.gitignore,该文件在a中没有,在b中有。
@@ -0,0 +1,8@@
代表两份文件有差异部分的起始行号,由于旧版本没有,故差异起始和结尾行号均为0;新版本则是从第一行至第八行存在差异。
后面的内容则为文件具体新增的内容。
Git 分支
Git在一个分支下的多次commit会形成一条commit链,而每一次commit就是链的其中节点,Git支持从任意commit中分离出一条单独的分支,并在分支中进行独立的开发。分支从某个节点分离,形成两条路径,两条路径共同保有分离节点及前序节点的所有内容,但在之后分支内部的开发中互不干扰,具体可表示为:
如图所示,当前共有三条分支,分别为main、Branch1、Branch2,两条支线分支从主分支的commit4分离出来,并在各自的分支上独自创建新的提交,此时三条分支实现了并行开发。
当主分支进行了commit5后,位于独立分支的Branch1和Branch2将无法看到主分支提交的内容;同理,两分支在进行自己分支上的commit5后,其它分支也无法看到这个commit5,但是这三条分支却能共同看到主分支上的commit1至commit4。从分支当中继续创建分支也是可行的。
当一个分支开发完毕后,需要合并到另一个分支,此时分为两种情况:
情况一:若两分支在分离后均产生了提交,则可以使用\(git\ merge\ Branch\)命令将需要合并的分支合并到当前位于的分支上,但是该种操作会产生新的提交分支,如上图所示,两个\(commit\ M\)分支即为合并产生的提交记录。
情况二:若某一分支在分离后没有新的提交,则可以使用快速合并,将未提交分支的头节点直接移动到有提交分支的最新一次提交,但是快速分支并不会产生提交记录。
分支的快速合并示意如下图所示:
git常见的分支命令分为以下几种:
| 命令 | 效果 |
|---|---|
| git branch | 查看本地分支 |
| git branch -a | 查看所有分支、包括远程分支(多人开发下) |
| git branch “分支名“ SHA | 从节点SHA创造一个新的分支但不切换,若不带SHA则从当前分支的头节点创造 |
| git switch “分支名” | 切换到某个分支,可以根据git branch进行确认 |
| git switch -c ”分支名“ SHA | 从节点SHA创造一个新的分支并切换,不带SHA则从当前分支的头节点创造 |
| git branch -d “分支名” | 删除某分支,但是若该分支有未合并的内容,分支将不会被删除 |
| git branch -D “分支名” | 强制删除某个分支,哪怕存在未合并内容 |
| git brach -m “分支名” | 给当前分支重命名 |
| git branch -m “旧分支名” ”新分支名“ | 给指定的旧分支名命名 |
| git merge ”分支名“ | 将某分支合并到当前分支 |
若两个分支在合并时同时对一个文件进行了修改,此时Git会提示文件冲突,需要决定具体保留哪个文件的分支。首先创建Master分支,并创建文件GitTest.py,输入内容后提交,并创建新的分支branch1。在branch1对GitTest.py修改并提交,切换回Master分支。在Master分支对GitTest.py进行修改,提交后输入命令\(git\ merge\ branch1\),如下图所示,git提示两版本冲突:
更细致地,git会指出冲突文件具体不一致的地方,如下图所示:
手动修改冲突文件至最终想要合并的版本,并将修改后的该文件使用\(git\ add\)添加进暂存区后,使用\(git\ commit\)添加进本地仓库,此时\(merge\)已经完成,合并后的Git树如下图所示:
Git与远程仓库
上述所有操作针对的都是本地仓库,要想真正实现开源以及多人合作,需要用到类似于Github、Gitlab、Gitee等远程仓库。以Github为例,首先在Github中创建一个远程仓库,如下图所示:

Github仓库的链接通常为:https//(git@)github/用户名/仓库名.git。如刚才创建的仓库即为https//(git@)github/violet796/GitTest.git。
创建好远程仓库后,需要用本地仓库和远程仓库取得连接,具体命令为: \[ git\ remote\ add\ origin\ Reporsitoryname \] 取得连接后,即可往远程仓库推送本地仓库的内容,具体命令为: \[ git\ push\ -u\ origin\ 分支名 \] 其中\(-u\)指的是$ –set-upstream\(,即建立跟踪关系,在第一次push时使用\)-u\(,可以将本地仓库的某一分支和远程仓库某分支绑定,形成**跟踪关系**,这样后续推送该分支时可以直接使用\)git push$命令。
关于推送到远程仓库的一些注意事项:
一:push 命令后的分支名指的是需要推送的分支名,不一定是当前分支;若直接使用\(git\ push\)命令,则默认将当前分支推送到远程仓库,前提是当前分支绑定了远程仓库的某分支
二:若推送的分支名在远程仓库中不存在,则远程仓库会创造一个同名的分支
三:若不想本地仓库的分支对应到远程仓库的同名分支,在建立跟踪关系时可以使用命令: \[ git\ push\ -u\ origin\ 本地分支名:远程分支名 \]
以建立不同分支名的跟踪,但这基本上用不到
四:可以使用\(git\ branch\ -vv\)命令查看本地仓库和远程仓库的跟踪项
五:判断本地仓库和远程仓库是否产生连接可以使用\(git\ remote\ -v\)命令
要将本地仓库的文件上传到远程的某个仓库,通常需要公钥和私钥文件,具体而言,在powershell中输入如下命令: \[ ssh-keygen\ -t\ ed25519\ -C\ \text{“GitHub邮箱"} \] 具体如下图所示,命令行后会提示密钥生成到了哪个文件当中:
找到对应的文件,发现已经生成公钥以及私钥,私钥保存在自己的电脑上。点开\(.pub\)后缀的文件夹,复制里面的内容,如下图所示:
打开Github,在settings的SSH and GPG keys中输入密钥的名字,并粘贴复制的公钥,点击Add SSH Key,即可完成公钥的添加,具体如下图所示:
添加公钥后,本机可以通过 SSH 被 GitHub 识别为对应账号;是否能 push 到某个仓库,还取决于该账号是否拥有该仓库的写权限。
\(Fin.\)