LV01-Git-04-Git本地仓库-10-贮藏与清理

本文主要是Git中贮藏与清理的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
点击查看本文参考资料
点击查看相关文件下载
--- ---

【说明】本节笔记的相关操作在Windows下进行,因为VS Code有个Git的插件,可以很直观的演示一些东西。由于Git安装后自带一个Git-Bash终端,所以就不用Win下的命令行啦,就用的这个终端,因为它里边的命令与Linux很类似,而windows中的命令行有些命令与linux并不相同,为了统一,还是用用Git自带的终端啦。另外VS Code是可以选择使用的终端的,我直接将VS Code使用的终端改成了git-bash,这样更方便一些。

一、应用场景

有时,当我们在项目的一部分上已经工作一段时间后,所有东西都进入了混乱的状态, 而这时我们想要切换到另一个分支做一点别的事情。 问题是,我们不想仅仅因为过会儿回到这一点而为做了一半的工作创建一次提交。 针对这个问题的答案是 git stash 命令。

贮藏(stash)会处理工作目录的脏的状态——即跟踪文件的修改与暂存的改动——然后将未完成的修改保存到一个栈上, 而我们可以在任何时候重新应用这些改动(甚至在不同的分支上)。

迁移到 git stash push

截至 2017 年 10 月下旬,Git 邮件列表上进行了广泛讨论,该讨论中弃用了 git stash save 命令, 代之以现有 git stash push 命令。主因是git stash push 引入了贮藏选定的 路径规范 的选项, 而有些东西 git stash save 不支持。

git stash save 不会很快就消失,所以不用担心它突然不见。 不过你可能想要迁移到 push 来获取新功能。

二、仓库准备

1. 初始化仓库并提交

我们在本地准备一个测试的仓库,并做一次提交,另外需要直接创建一个分支:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git init
Initialized empty Git repository in D:/git_test/.git/

$ touch readme.md
$ touch test.md

$ git add .

$ git commit -m "feat:首次提交"
[master (root-commit) 6fdcbbf] feat:首次提交
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 readme.md
create mode 100644 test.md

$ git branch dev

2. 文件内容与提交记录

我们记录一下各个分支上这两个文件的内容:

2.1 master分支

image-20230624202757705

2.2 dev分支

image-20230624202832487

三、贮藏工作

这里贮藏的修改我们在master分支上进行。

1. 产生文件改动

为了演示贮藏,我们需要进入项目并改动几个文件,然后可以暂存其中的一个改动:

image-20230624203432533

如果运行 git status,可以看到有改动的状态:

1
2
3
4
5
6
7
8
9
10
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.md

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.md

我们修改仓库中的两个文件,但是,我们只将readme文件添加到暂存区,这个时候就会出现上边的文件状态。

2. 切换分支

我们现在不提交上边做的改动,但是又想切换分支,我们来尝试一下:

1
2
3
4
$ git checkout dev 
Switched to branch 'dev'
M readme.md
M test.md

我们现在看一下处于哪个分支:

1
2
3
$ git branch 
* dev
master

会发现,我们切换分支成功了,我们看一下现在的dev分支下的文件状态:

image-20230624074209583

会发现,居然和master分支一样,这两个文件都被修改了,还添加到了暂存库,这不就混乱了吗?其实在使用git的过程中,多数时候切换分支的时候发现原来所处的分支中有没有提交的记录时,是会停止切换分支,报错的,但是这里没有,就有些奇怪,不过一样的结果。这里虽然没报错,但还是以影响到了我们dev分支的文件,这个时候我们并不想把做了一半的工作进行提交,但是又想去另一个分支做一些事情。这个时候就可以用贮藏命令啦。

我们这里先切换回master分支:

1
2
3
4
$ git checkout master 
Switched to branch 'master'
M readme.md
M test.md

3. 贮藏修改

3.1 命令说明

贮藏命令是stash,如下所示:

1
2
3
git stash
# 或者
git stash push

贮藏命令可以将我们相对于最新一次提交记录的差异存储在栈上。另外Git允许我们做多次贮藏,后边再看。

3.2 使用实例

上边我们已经回到了master分支,我们执行贮藏命令:

1
2
$ git stash push
Saved working directory and index state WIP on master: 6fddbcf feat:首次提交

然后我们来看一下当前的文件状态和提交记录:

1
2
3
$ git status 
On branch master
nothing to commit, working tree clean

发现,工作区是干净的,并且也没有产生提交记录,这个时候我们再切换分支就不会有任何问题啦。这时候再去看文件,就会发现文件中我们所做的修改都消失啦。

4. 查看贮藏内容

我们要是想查看贮藏了哪些内容怎么办?

4.1 命令说明

我们可以通过以下命令查看贮藏的内容:

1
git stash list

4.2 贮藏信息说明

我们查看贮藏内容的时候一般会有如下打印信息:

1
2
3
stash@{0}: WIP on branch_name: commit_id commit_info
stash@{1}: WIP on branch_name: commit_id commit_info
# ......
  • stash@{1} :表示贮藏修改的编号,数字越小,贮藏时间越靠前,数字越大,贮藏越旧。
  • branch_name :进行贮藏操作的时候所处的分支,也就表示了这一个贮藏是哪一个分支上进行的贮藏。
  • commit_id :贮藏的时候,此分支上最新的条记录的hash值,也就是在哪个提交记录的基础上做的修改被贮藏了。
  • commit_info :贮藏的时候,此分支上最新的条记录的提交信息。

4.3 使用实例

我们来看一下刚才贮藏的内容:

1
2
$ git stash list
stash@{0}: WIP on master: 6fddbcf feat:首次提交

这里可以注意下,每一次的贮藏,前边都会有一个编号,例如stash@{0}中的0就是这一次贮藏的编号,后边会有用。

四、应用贮藏

我们切换分支,完成相应的任务后,要继续回到master分支继续刚才没有完成的事情,这个时候就需要恢复贮藏的内容,也可以叫应用贮藏

1. 命令说明

我们可以通过以下命令来恢复贮藏的内容:

1
git stash apply

那要是有多个贮藏呢?就像刚才的情况。如果想要应用其中一个更旧的贮藏,可以通过名字指定它,像这样:

1
git stash apply stash@{n}

n就表示贮藏的编号,n = 0表示最近一次注册那个,数字越大,表示贮藏越旧。 如果不指定一个贮藏,Git 认为指定的是最近的贮藏

2. 使用实例

我们来试一下恢复最近一次的贮藏:

1
git stash apply 

然后我们会看到以下信息:

image-20230624080518416

我们会发现,之前做的修改回到了工作区,但是有一个变化,那就是,两个文件的修改都出现在了Changes not staged for commit的下边,看起来像是吧暂存区中的修改也撤回到未使用git add之前的状态了。然后我们查看文件内容的话,就可以看到 Git 重新修改了当我们保存贮藏时撤消的的内容了。

4. 可能会产生冲突?

在上边恢复贮藏的实例中,当我们尝试应用贮藏时有一个干净的工作目录,并且尝试将它应用在保存它时所在的分支。 并不是必须要有一个干净的工作目录,或者要应用到同一分支才能成功应用贮藏。 可以在一个分支上保存一个贮藏,切换到另一个分支,然后尝试重新应用这些修改。 当应用贮藏时工作目录中也可以有修改与未提交的文件——如果有任何东西不能干净地应用,Git 会产生合并冲突。

我们可以来尝试一下,我么还是在master分支上进行操作。我们知道贮藏修改后,工作区的文件会恢复到修改之前的状态,刚才我们应用了贮藏,这里我们先撤销文件的修改,也就是会回到应用贮藏之前,我们直接执行下边的命令即可:

1
git checkout -- .

然后当前工作区的文件就回到了首次提交的时候的空文件了:

image-20230624204122573

我们知道上边贮藏的时候的修改中我们修改了这两个文件的第一行,所以我们再次修改这两个文件的第一行:

image-20230624204424836

然后再应用贮藏,这个时候就会出现类似以下的报错:

image-20230624204534493

这种情况下就无法应用贮藏了这里还是需要注意一下的。演示完毕后我们清空一下这个工作区,方便后续的测试学习:

1
git checkout -- .

5. 回到贮藏的状态?

还记得前边我们应用贮藏的时候,发现恢复的修改都是没有被提交到暂存区的,但是我们进行贮藏的时候,是吧readme文件提交到暂存区了的,那么如何在应用贮藏的时候回到注册那个修改的时候的状态呢?

5.1 命令说明

想要完全跟贮藏那个的时候状态一样,我们需要加上``–index`参数:

1
git stash apply --index

5.2 使用实例

我们接下来来看一下,我们执行以下命令:

1
git stash apply --index

然后我们会看到如下信息:

image-20230624205116412

发现这个时候,应用的贮藏跟我们贮藏修改的时候的状态一模一样啦。

五、移除贮藏

1. 情况说明

还记得上一步,我们使用git stash apply --index命令应用了一次贮藏,应用完贮藏,贮藏的记录还在吗?我们来看一下:

1
2
$ git stash list 
stash@{0}: WIP on master: 6fddbcf feat:首次提交

会发现贮藏的信息还在,如果不移除的话,它将会一直存在于栈上。

2. 命令说明

我们可以使用以下命令来移除贮藏记录:

1
git stash drop stash@{n}

stash@{n}就表示贮藏列表前边的那个编号。

3. 使用实例

我们来实际验证一下:

image-20230624205600592

会发现,贮藏的记录确实消失了。