02-本地库基本操作

发布时间 2023-11-15 10:44:46作者: 讨厌敲代码的老郭

02-本地库基本操作

本地库基本操作

在一指定文件夹右键使用 "git bush" 指令打开 git 命令行工具,即可进行本地库操作。

1. 本地库初始化

在当前文件夹中初始化 git 工具环境。

$ git init

生成一个 .git 隐藏文件夹,目录中存放的是本地库相关的子目录和文件,不能随意删除和修改。

2. 本地库基本操作

2.1 添加

将工作区中文件添加到暂存区,在暂存区进行文件覆盖及对应状态修改,可以使用 add 添加命令。

  • 仅提交指定的文件到暂存区
$ git add [文件路径/文件名]

若需同时操作多个文件,只需将各文件名一次书写,空格隔开即可,后同

  • 将工作区所有文件提交到暂存区
$ git add .
// 或者
$ git add -A

一般采用全部提交即可。即使是未修改文件,执行覆盖操作也不影响。git 会自动追踪文件的变化状态。

当工作区文件使用 add 命令提交至暂存区之后,git 才可以开始追踪文件的变化。

2.2 撤回

希望将工作区和暂存区的修改进行撤回,可以使用 restore 或 checkout 命令。

  • 将工作区中已经被 git 追踪的文件修改撤回至最后一次提交暂存区的状态
$ git restore --worktree [撤回文件名称]
$ git restore --worktree .

被追踪的文件即使删除也可以被还原

  • 仅将暂存区最后一次提交的撤回,但不修改工作区文件
$ git restore --staged [撤回暂存区提交文件名称]
$ git restore --staged .

相当于取消最后一次工作区向暂存区的添加

  • 将工作区还原为最后一次提交内容
$ git checkout [撤回文件名称]
$ git checkout .

2.3 提交

2.3.1 普通提交

将暂存区中文件添加到本地库,在本地库进行文件覆盖及对应状态修改,可以使用 commit 提交命令。

  • 提交暂存区文件到本地库,并附带功能改动描述
$ git commit -m '提交信息描述'
  • 将工作区和暂存区文件一起提交到本地库(不推荐)
$ git commit -a -m '提交信息描述'

提交功能是 Git 仓库的关键部分之一,执行提交命令时会自动生成一条提交历史记录,作为项目代码变化的记录日志,所以提交的信息应该尽可能的简短精确,能够描述清楚当前提交的内容,方便在日后能够查看到代码变化的过程。所以,应尽可能的遵从一定的规范。

如果提交时较之前没有任何文件变化,即使执行提交命令也不会产生提交记录。git 会认为这是一次无效提交。

2.3.2 追加提交

追加提交一般指的是在不添加新提交记录的前提下修改最近一次的提交。

当你刚提交过代码,发现又有些小问题需要修改,但又不想新增额外的历史提交记录(因为修改的部分和最后一次提交做的是同一件事),这时可以使用如下命令进行追加提交。

  • 追加提交,并修改相应的提交信息描述
$ git commit --amend -m '提交信息描述'
  • 追加提交,但不修改相应的提交信息描述,仍使用之前的描述
$ git commit --amend --no-edit

2.4 状态查看

查看项目文件在工作区,暂存区的项目文件增删改的状态及变化,以及哪些修改还未进行 add 及 commit 提交。

2.4.1 查看详细状态

使用命令:

$ git status

可以得出如下部分示例结果:

On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   index.html
        new file:   style.css

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   index.html
        deleted:    style.css

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        main.js
  • On branch master:表示当前所在分支
  • No commits yet:表示暂存区文件还未进行提交。若已提交,则不显示本条信息
  • Changes to be committed:显示即将由暂存区向本地库提交的文件修改
  • Changes not staged for commit:显示还未由工作区向暂存区提交的文件修改
  • Untracked files:表示还未由 git 跟踪的文件,即只在工作区存在,还未经过 add 提交过的文件

只要文件经过 add 命令提交过,git 就会开始追踪该文件的变化。当进行状态查看时,会显示当前文件在 git 文件追踪工作流程中的最后一次修改的状态:

  • new file:表示为新增文件
  • modified:表示该文件被修改
  • deleted:表示该文件已被删除

2.4.2 查看简易状态

使用命令:

$ git status -s

可以得出如下部分示例结果:

A  css/style.css
AM index.html
AD main.js
?? text.txt
  • ??:表示该文件还未被 git 进行追踪,即未进行 add 添加的文件
  • A:表示已经被提交到暂存区的文件
  • AM:表示已经被提交到暂存区,但是又在工作区进行修改的文件
  • AD:表示已经被提交到暂存区,但是又在工作区被删除的文件
  • M:表示已经提交到本地库,但是又在工作区进行修改的文件
  • D:表示已经提交到本地库,但是又在工作区被删除的文件

2.5 查看历史记录

每次使用 git commit 命令都会在本地版本库生成一个 40 位的哈希值,这个哈希值也叫 commit-id。commit-id 在版本回退的时候是非常有用的,它相当于一个快照,可以在未来的任何时候通过命令回到这里。

2.5.1 查看完整历史记录

查看 git 本地库历史提交记录的完整形式,可以使用如下命令:

$ git log
  • 显示的结果按照时间顺序排列,最新的在前
  • 只显示提交记录,不显示操作记录
  • 在当前位置所在记录会显示 (HEAD -> master)

显示结果展示方式后同

其中历史记录单条结构为:

commit [提交记录完整 hash 值] (本地库当前历史记录位置)
Author: [签名项目作者] <签名邮箱>
Date: [提交时间]

    [提交描述信息]

如果历史记录过多,单屏显示不完整,可以使用 空格 向下翻页,"b" 按键向上翻页,"q" 按键退出查看。

  • 提交记录完整 hash 值:是长度为 40 的字符串编码,表示提交记录标记,在当前项目历史记录中为唯一值。
  • 本地库当前历史记录位置:显示的 HEAD 表示本地库所在的提交记录位置
  • 项目作者:显示最近的项目签名信息,格式为 username < email >
  • 提交时间:该条记录提交时间
  • 提交描述:该条记录提交描述

2.5.2 查看历史记录其他方式

  • 仅显示完整 commit-id hash 值和提交描述信息
$ git log --pretty=oneline

pretty 意为:漂亮的

其中历史记录单条结构为:

[提交记录完整 hash 值] [提交描述信息]
  • 仅显示 commit-id hash 值前 6 位和提交描述信息
$ git log --oneline

其中历史记录单条结构为:

[提交记录 hash 值前 7 位] [提交描述信息]
  • 显示 HEAD 指向发生改变时间列表。
$ git reflog

简单的说就是查看 git 的操作记录(如提交、历史回退,合并等)。这个记录不会持久保存,git 会自动清除较为久远的记录。

其中历史记录单条结构为:

[conmit_id 值前 6 位] [HEAD@{ 移动到指定版本需要的步数 }] commit: [提交的 commit 描述]

可以获取以下示例结果:

[conmit_id] (HEAD -> master) HEAD@{0}: commit: [提交描述]
[conmit_id] HEAD@{1}: commit: [提交描述]
[conmit_id] HEAD@{2}: commit: [提交描述]
    ...
[conmit_id] HEAD@{n-1}: commit: [提交描述]
[conmit_id] HEAD@{n}: commit (initial): [(第一次)提交描述]

当需要进行版本的前进或后退时,除了可以直接使用 commit_id 之外,还可以使用 HEAD 指令控制后退的步数。HEAD 默认指向工作区当前所在位置。

  • HEAD^ 表示后退一步,一个 ^ 表示一步
  • HEAD~n 表示后退 n 步

2.5.3 图形化显示历史提交记录

绘制一个 ASCII 图像来展示提交历史的分支结构。它经常和 --oneline 和 --decorate 两个选项一起使用,这样会更容易查看哪个提交属于哪个分支。

$ git log --graph

可以使用插件代替此项功能 vscode:git-graph

2.5.4 其他配置属性及其用法

属性 用法
grep="关键字" 查找日志记录中(commit提交时的注释)与关键字有关的记录
all 将所有记录都详细的显示出来
author "username" 查找这个作者提交的记录
reverse commit 提交记录顺序翻转
before 查找规定的时间(如:1天/1周)之前的记录
num git log -10 显示最近10次提交
stat 显示每次更新的文件修改统计信息,会列出具体文件列表
abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符
pretty=format:"xxx" 定制要显示的记录格式
p 显示每次提交所引入的差异(按 补丁 的格式输出)

2.6 版本切换

2.6.1 版本重设

使用 reset 命令可以将当前分支回退到指定历史记录版本。

该命令一般用于删除提交的历史记录,回滚重设到某一历史版本,尽管它通常被顺便用来撤销暂存区和工作区的修改。

当使用 reset 回滚到了某个版本后,该版本之后的历史提交记录会被删除掉。所以它应该只被用于本地修改,你永远不应该重设和其他开发者共享的快照。

++大多数的使用场景是,只用来在本地回退撤回最后一次的提交记录。++

若仍需要恢复之前的版本,可以使用 reflog 查看操作历史,找到被删除的版本号,但是由于 reflog 有保存时间,所以不是总能找到的。

$ git reset [commit_id] --[命令配置参数]

其中 commit 默认值为 HEAD,意为最后一次提交版本

不同的参数对应不同的回退操作:

  • 仅撤回 commit 提交,并将本地库重设为指定版本历史代码,但不撤回 add 提交,不修改工作区代码
$ git reset [commit_id] --soft
  • 同时撤回 commit 和 add 提交,并将本地库重设为指定版本历史代码,但不修改工作区代码
$ git reset [commit_id] --mixed
  • 同时撤回 commit 和 add 提交,并将工作区代码重设为指定版本历史代码
$ git reset [commit_id] --hard

这里会修改工作区代码,慎重使用

2.6.2 版本恢复

使用 revert 命令可以将当前分支恢复到指定历史记录版本的状态。

$ git revert [commit_id]

使用 revert 恢复版本并不是简单的代码回撤,操作的目标是撤销从指定 commit_id 版本开始到当前版本的代码内容,也就是在指定 commit_id 版本前一提交版本代码基础上进行重写。所以,revert 命令的操作逻辑过程就是获取指定 commitid 版本的前一版本代码与当前版本进行工作区合并,然后在工作区代码会展示代码冲突,待手动处理冲突(重写撤回代码)后需要自己手动提交一次,将期望回退的结果作为新的提交版本继续编写代码。

版本重设 reset 和版本撤销 revert 的区别

revert 和 reset 相似的地方都是可以将本地库代码回退到某一历史记录版本,但是,和 reset 实现的方式不一样。

  • reset 在回退到指定历史记录版本后,该版本之后的记录会被删除
本地库代码变化:
1 --> 2 --> 3 --> 4 -(reset 2 id)-> 2

此时查看历史记录为:1 --> 2
3 和 4 是被删除掉的
  • revert 在回退到指定历史记录版本后,是新提交了一个指定历史记录版本的代码,本质还是一个新提交
本地库代码变化:
1 --> 2 --> 3 --> 4 -(revert 2 id)-> (1 + 4 合并结果)

此时查看历史记录为:1 --> 2 --> 3 --> 4 --> 5
2、3 和 4 版本记录是仍然保留的,但是 5 中保留的是在 1 的基础上重写 2、3 和 4 的代码结果

对比之下,撤销(revert)应该用在想要移除某个项目提交历史的时候,重设(reset) 应该用在撤销最后一次提交历史的时候。撤销(revert)被设计为撤销公共提交的安全方式,重设(reset)被设计为重设本地更改。

2.7 缓存工作区

如果在日常开发过程中,需要临时的处理一个紧急的 bug 修复任务,当时工作区当前正在开发功能中,短时间无法完成,无法直接提交到仓库,这时可以使用 stash 命令先将工作区和暂存区内容缓存一下,然后切换到出现 bug 的分支,当 bug 修复后,再使用 stash 命令恢复之前的工作内容即可。

这里的缓存不在 git 提交堆栈范围之内,是额外进行存储的

2.7.1 提交缓存

  • 将当前工作区和暂存区修改提交到缓存区
$ git stash
  • 由于缓存区提交默认不包含 git 未追踪文件(即没有 add 过的文件),可以使用如下命令缓存未追踪文件
$ git stash -u

鉴于此,在缓存前,最好先执行一次 add 命令

  • 添加缓存并备注缓存名称
$ git stash save <stachname>

2.7.2 查看缓存

由于可以进行多次缓存,可以查看缓存列表:

$ git stash list

查看结果:

stash@{缓存索引}: On <分支名称>: 缓存备注

2.7.3 恢复缓存

在命令中使用缓存记录时,缓存标记可能需要添加双引号 "stash@{缓存索引}"

  • 恢复指定缓存,并删除对应缓存记录
$ git stash pop
$ git stash pop stash@{缓存索引}

若不指定缓存,则默认恢复并删除最新缓存,后同

  • 恢复指定缓存,但不删除对应缓存记录
$ git stash apply
$ git stash apply stash@{缓存索引}
  • 单纯删除缓存记录
$ git stash drop stash@{index}
  • 删除所有缓存记录
$ git stash clear
  • 查看缓存记录中修改了哪些文件
$ git stash show stash@{index}
  • 查看缓存记录中修改了哪些文件及对应修改内容
$ git stash show -p stash@{index}

2.7 diff

$ git diff

略...

2.8 文件重命名

对于已经提交过的文件需要使用命令重命名。

$ git mv [原文件名] [新文件名]

若新文件名已经有对应的文件存在,可以使用 -f 配置强制重命名并覆盖已有文件。

$ git mv -f [原文件名] [新文件名]

2.9 文件删除

工作区文件删除直接手动删除即可。暂存区文件删除则需使用命令删除。

  • 只删除暂存区的文件,不会删除工作区的文件
$ git rm --cached [filename] 
  • 同时删除工作区和暂存区文件
$ git rm -f [filename]

将指定的文件从暂存区删除,暂存区保存的文件追踪状态为删除状态,若再进行提交,则版本库就会相应的删除对应文件,也就意味着不再追踪该文件变化。

2.10 文件提交忽略

.gitignore 文件作用就是告诉 Git 哪些文件不需要添加到版本管理中。

2.10.1 忽略规则

  • 以斜杠/开头表示目录;
  • 以星号*通配多个字符;
  • 以问号?通配单个字符
  • 以方括号[]包含单个字符的匹配列表;
  • 以叹号!表示不忽略(跟踪)匹配到的文件或目录

此外,git 对于 .gitignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效。

语法部分示例

/mtk/       过滤整个文件夹
*.zip       过滤所有.zip文件
/mtk/do.c   过滤某个具体文件

!src/       不过滤该文件夹
!*.zip      不过滤所有.zip文件
!/mtk/do.c  不过滤该文件

2.10.2 创建 .gitignore 文件

由于 windows 下不能直接创建 . 开头名称文件,所以可以借助编辑器。

或者先创建 gitignore.txt 文件,然后使用如下命令重命名:

$ ren gitignore.txt .gitignore

2.10.3 常见忽略内容

# dependencies  npm包文件
/node_modules

# production  打包文件
/build

# misc
.DS_Store

npm-debug.log*
  • .DS_Store:Mac OS X用来存储文件夹当前文件夹元信息(图标、位置等)
  • npm-debug.log:使用 npm i 安装错误时会生成的文件

如果不慎在创建 .gitignore 文件之前就已经进行的代码 add 添加或 commit 提交,那么即使在 .gitignore 文件中写入新的过滤规则,这些规则也不会对需要忽略的文件起作用,Git 仍然会对所有文件进行版本管理。简单来说,出现这种问题的原因就是在文件进行添加或提交之后, Git 已经开始管理这些文件了,所以你无法再通过过滤规则过滤它们。因此一定要养成在项目开始就创建 .gitignore 文件的习惯,否则一旦 push,处理起来会非常麻烦。