跳过正文

丙加·番外·ALLTALE 与 神之手(Git 的使用)

·615 字·3 分钟·
目录

本节将引导读者学会使用最基础的 git 版本控制功能。

12¾.1 ハロー ギット
#

就算代码库被 rm -rf
我也想,
使用 git reset --hard 回见到你——

这种让一切“重来”的底气,源于我们手中的强大工具:Git

Git 是一个免费且开源的分布式版本控制系统,旨在快速高效地处理从小到大的所有项目。(引自 Git 官网中文官网

通过 Git,我们不仅可以轻松维护代码的无数个历史版本,还能从清晰的提交记录中追溯每一次修改的意图。这极大地方便了复杂项目的开发与维护。

Git “分布式”的特性更是团队协作的利器。它没有绝对的中心服务器,每个开发者的本地仓库都是完整的副本。基于内容差异和哈希校验的同步机制,让分支、合并与代码评审变得高效可靠。程序员可以轻松的在每一个 IF线(代码分支) 之间跳跃,还能对它们进行分支、合并等操作。全球最大的代码托管平台 GitHub 正是得名于 Git。

Git 还像是“神之手”。误删文件、改出 Bug、甚至整个项目目录被清空?别慌。只要曾经提交过,你就可以从容地从某个历史节点恢复如初。

从个人实验到企业级项目,Git 已成为现代软件开发不可或缺的基础设施。接下来,我们将从零开始,掌握 Git 最核心的操作,掌握穿越时间、修改现实的力量! 仅限于你的仓库内

12¾.2 准备工作
#

我们首先需要正确地下载和安装 Git。

前往 Git - Install 下载正确的安装包

然后打开安装包,UAC 弹窗记得通过一下。基本上保持默认就好,但是,选择编辑器(Choosing the default editor used by git)的时候记得改成自己习惯的!!!

installation

这样就完成了安装

安装之后…
#

这时,打开任意终端(开始菜单图标右键 - “终端”(或者会是命令提示符/Powershell))

输入:

git --version

你会立刻看到版本信息,说明安装成功。

这之后,输入下面命令进行其它必要配置:

# 设置你的身份信息(提交时会用到)
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"

# 关闭文件名转义
git config --global core.quotepath false

12¾.3 驾驭“神之手”
#

Git 的工作看起来就是将历史线的节点进行记录、分支、合并和移动的操作。不过我们这里先只学习“书写历史”的部分。熟练之后,读者可以自行查阅、探索分支和合并操作。

12¾.3.1 初始化:美好 我看未必 故事的起点
#

找到一个目录,实在不行新建一个,右键(找不到就 Shift + 右键)- 在终端中打开(或者 Git Bash,Powershell、命令提示符都可以),打开 git 的终端。

输入并回车

git init
image-gitproc_init

这样就完成了仓库初始化(我安装了 oh-my-posh,提示符也同步显示了仓库的信息)

12¾.3.2 第一次提交
#

随便创建一点文件

image-gitproc_init_editing_files

然后输入:

git add .
# 由于你现在在仓库根目录下,所以递归向下搜就能扫到所有文件
# 如果你不在根目录,可以使用
git add -A

完成后什么都不会输出,但这个时候,git 已经完成了对 . 目录(也就是当前目录)的扫描,将文件从工作区(就是仓库根目录,你做编辑的区域)放入暂存区,准备好了提交。

image-gitproc_add

碎碎念之一:增加特定文件
#

如果你只想增加特定的文件或者目录,那么就将 “.” 替换为对应的东西。

# 只添加某个文件
git add filename.txt

# 批量添加某个文件夹下所有东西
git add folder/

# 添加所有修改的文件
# ** 只添加已跟踪的文件,也就是如果新增了文件,新文件不会被跟踪
# 这一点与 -A 有所不同
git add -u

碎碎念之二:忽略文件
#

​ 如果需要在批量操作的时候忽略特定的文件,那么,创建一个名为 .gitignore 的文件,用记事本打开它,将需要忽略的文件/文件夹以相对路径的形式添加进去即可

​ 比如要忽略 𝙿𝚑𝚒𝙻𝚒𝚊𝟶𝟿𝟹,那么,输入:

./𝙿𝚑𝚒𝙻𝚒𝚊𝟶𝟿𝟹

即可。由于 𝙿𝚑𝚒𝙻𝚒𝚊𝟶𝟿𝟹 就在仓库根目录,所以是 ./𝙿𝚑𝚒𝙻𝚒𝚊𝟶𝟿𝟹,如果有文件:位于仓库下的 DATA - ChrysosHeirs - PhiLia093 - memory_pb6b5z3qsns33pxm,那么就是:DATA/ChrysosHeirs/PhiLia093/memory——pb6b5z3qsns33pxm

如果是目录,建议加上 / 结尾

更多的例子:

# 忽略所有 .log 文件
 *.log
# 忽略 build/ 目录
build/
# 忽略所有 .tmp 文件,但保留 important.tmp
*.tmp
!important.tmp

你还可以在 GitHub 找到更多参考。


要查看 git 扫出了什么,输入:

git status
image-gitproc_stat

git 展示了距离上一次提交的更改。

如果你的文件名有 Unicode 字符,界面可能会长这样(比如 𝙿𝚑𝚒𝙻𝚒𝚊 的字符不是标准英文字符,是为数学公式设计的 Unicode 版本):

image-wired-unicode-escape

请输入:

git config --global core.quotepath false

关闭转义序列,然后重试。

这时你可以确认是否正确(git diff HEADq 退出),如果正确,那么就可以提交了(没有的话就回去改然后重新 add

输入:

git commit
image-gitproc_edit_COMMIT_MSG

这时会打开之前说的默认编辑器(我是 vim),你可以编辑提交信息,# 是注释行会被忽略。提交信息是你回顾历史时最直接的媒介,请务必认真填写。注意如果没有任何提交信息,git 会直接拒绝你的提交。

image-gitproc_commit_finished

现在文件从暂存区存入了提交。

image-gitproc_commit

你也可以使用

git commit -m "提交信息"

来避免打开编辑器

现在,你已经学会了“记录”的操作。

那么,就去书写属于你的浪漫故事吧~

小结 依旧增删改查
#

git 的操作也算得是一种对数据的”增删改查“操作了。我们刚才主要学习了”增“的操作

初始化:

git init

添加:

# 文件或目录
git add <path>
# 全加
git add -A
# 更新而不增加文件
git add -u

检查状态:

git status

提交:

git commit [-m MSG]

12¾.3.3 回滚:终末的力量
#

如果写错了代码、不小心删除了内容,我们就需要从「过去」寻找答案:

# 检查所有提交
git log
image-gitproc_log

显示有两个提交。

回滚有几种方式,分别有不同的强度,从“软”到“硬”分别如下:

1. 软回滚(保留修改)
#

如果只是想撤销提交但保留修改内容:

# 撤销最近一次提交,但保留修改内容在暂存区
git reset --soft HEAD~1
# 如果只是恢复特定文件,那么加上文件名即可
# 此时HEAD的头部不会发生移动
git reset --soft HEAD~1 a.txt CMakeList.txt
image-gitproc_soft_reset

--soft 不会更改工作区,会将提交撤销,提交的文件放入暂存区,此时你就可以为这个提交补充文件,免得额外增加一次提交

注意,如果只是像第二个命令一样恢复一个或几个文件,HEAD的头部不会发生移动,后面的回滚同理。

2. 混合回滚
#

# 撤销最近一次提交,完全放弃暂存区
git reset HEAD~1
# 等效于
# git reset --mixed HEAD~1

# 如果只是恢复特定文件,那么加上文件名即可
git reset HEAD~1 a.txt CMakeList.txt
image-gitproc_mixed_reset

--mixed 会直接将提交放回工作区,所以,如果你最初提交了文件 file1.txtfile2.txt,提交后又修改了 file1.txt,这回导致工作区的 file1.txt 与提交的 file1.txt 冲突。此时不能使用 --mixed

3. 硬回滚(放弃修改)
#

如果想彻底丢弃当前所有修改,回到某个过去的提交状态:

# 回滚到指定的提交
# hash只需要前几位就好
# 比如 620073a
# 当然,HEAD始终指代最新的提交的哈希
# HEAD~1,HEAD~2分别代表HEAD的前一次、前两次提交
git reset --hard <commit-hash>

# 如果只是恢复特定文件,那么加上文件名即可
git reset --hard <commit-hash> a.txt CMakeList.txt

image-gitproc_hard_reset 警告:这是最强的回滚形式,会清除所有工作区的内容!谨慎使用。

4. 使用 revert 安全回滚
#

如果是在公共分支上,推荐使用 revert 创建一个新的提交来撤销之前的修改:

# 撤销指定的提交
git revert <commit-hash>

这会生成一个新的提交,正好复制了 <commit-hash> 中的内容。

小结
#

总结一下,git 的回滚主要语法有:

# 真·回滚
git reset <--soft|--mixed|--hard> <hash> [filename1] [filename2] ...
# 复刻一份
git revert <commit-hash>

12¾.3.4 对比:选哪边?
#

image-gitproc_diff_meme

对比清晰,确实够清楚wwwwww

git diff 命令可以对比一对提交或者文件。基本语法是:

git diff <obj1> <obj2>

比如 git diff [branch1] [branch2] 可以对比两个 branch 的差异;git diff [file1] [file2] 可以对比文件的差异。(你可能意识到了分支名和文件名可能冲突,我们稍后讨论)

另外,

git diff --staged [file]

可以将工作区的 [file] 与暂存区中的 [file] 进行对比。(也可以使用别名 --cached

如果不指定文件 [file],那么 git 就会展示所有文件的对比。如果不想吵到眼睛,那么可以使用 --stat 只显示摘要。

--staged 替换为提交的哈希值,那么就会改为对比工作区与具体提交,语法与 --staged 几乎一样,只是往往会插入一个分隔符避免将文件名与分支名混淆。举个例子,你 恰好 有一对文件 CAFEBABECAFEDEAD。然后 恰好 也产生了提交号 CAFEBABECAFEDEAD。那么:

git diff CAFEBABE CAFEDEAD

就会优先对比分支 CAFEBABECAFEDEAD,而不是文件对比。那么,如何进行区分呢?

可以使用 .. 连接两个提交:

git diff CAFEBABE..CAFEDEAD

使用 -- 强制指定文件

# 将指定提交 <CAFEBABE> 的文件与工作区的文件 CAFEDEAD 进行对比
git diff CAFEBABE -- CAFEDEAD
# 单纯对比俩文件
git diff CAFEBABE -- CAFEDEAD -- 

但这种语法过于诡异,占位符 -- 的位置不 那么 便于理解,我们不多讲。如果要更清晰地体现语义,其实可以加一个 ./(或者具体路径):

git diff CAFEBABE ./CAFEDEAD
git diff ./CAFEBABE ./CAFEDEAD

这样就保持了语法的一致性,好记又好用了。

image-gitproc_diff
1-比较提交和提交
2-比较提交和文件
3-摘要式
4-比较两文件

最后,其实 diff 还有三个点连接提交的语法:

git diff CAFEBABE...CAFEDEAD

它的含义是,寻找这两个提交最近的共同祖先 X,然后将 XCAFEDEAD 进行对比。主要用于对比带有分支结构的提交。

但这完全可以使用等效且更清晰的语法替代:

git diff --merge-base CAFEBABE CAFEDEAD

碎碎念:不会有杂鱼退不出对比界面吧~♡

使用方法几乎和 vim 一样,无需多言。

不会还有人不会 Vim 吧~不会吧不会吧

小结
#

总结一下 git diff 的语法:

git diff [--merge-base] [--stat] <object1> <object2>

其中:

  • [--merge-base] 只能用于分支对比,将 <object2> 与两分支的共同祖先 X 进行对比;

  • <object> 具体可是 <commit-hash | filename | --staged>

    • 可以对比:提交与提交、提交与暂存区、提交与文件、暂存区与文件、文件与文件。
  • [--stat] 用于显示摘要而不显示具体内容

    Git 常见的工作流是: 0. git init 初始化仓库

    1. 编辑文件
    2. git add <file>(可以在根目录 add .) 将修改添加到暂存区 - 可以使用 git status 检查状态,git diff 检查修改内容
    3. git commit 将暂存区的修改提交到本地仓库 - 可以使用 git log 检查提交历史
    4. (如果需要)使用 git resetgit revert 回滚到之前的提交

12¾.2147483647 结语
#

掌握了这些“增删改查”的命令,你就已经拥有了操控仓库历史的基本神力。无论是记录当下的灵感(commit),还是回溯过去的错误(reset/revert),亦或是审视变迁的细节(diff),你都能得心应手。

但这只是“神之手”的冰山一角。当你需要同时推进多个实验性功能,或是与他人协作时,分支合并的力量将真正展现出 Git 的魔力。在未来的章节,我们将跳出线性的历史,探索平行世界的奥秘。

命令提示符@CommandPrompt-Wang
作者
命令提示符@CommandPrompt-Wang