保存正在进行的工作

GitBeginner
立即练习

介绍

欢迎回来,Git 探索者!今天,我们将深入研究 Git 中用于管理正在进行的工作(work-in-progress)最实用的功能之一:储藏(stash)。你是否曾遇到过这样的情况:正忙于开发某个功能,突然需要切换到另一个任务?Git stash 就是为了解决这种困境而生的!

你可以把 Git stash 想象成一个神奇的抽屉,你可以把没写完的代码暂时存放在里面。它让你能够快速切换上下文,而无需提交那些只做了一半的工作。当你需要切换分支、拉取更新或处理紧急的漏洞修复(bug fix)时,这个功能极其有用。

在本实验中,我们将探索如何使用 Git stash 保存你正在进行的工作、如何应用已储藏的更改、如何从储藏中创建分支、管理多个储藏以及清理储藏。完成本实验后,你的 Git 工具箱中将增添一件强大的利器,让你的工作流变得更加顺畅和灵活。

让我们开始解锁 Git stash 的力量吧!

这是一个引导实验,提供了逐步的指令来帮助你学习和练习。请仔细遵循说明完成每个步骤并获得动手经验。历史数据表明,这是一个 初学者 级别的实验,完成率为 94%。它获得了学习者 97% 的好评率。

设置工作区

在深入研究储藏功能之前,我们先建立一个实验用的工作区。我们将创建一个新目录,初始化一个 Git 仓库,并添加一些初始内容。

打开你的终端并输入以下命令:

cd ~/project
mkdir git-stash-lab
cd git-stash-lab
git init
echo "## Git Stash Lab" > README.md
git add README.md
git commit -m "Initial commit"

让我们分解一下这些命令的作用:

  1. cd ~/project:将当前目录切换到主目录下的 "project" 文件夹。
  2. mkdir git-stash-lab:创建一个名为 "git-stash-lab" 的新目录。
  3. cd git-stash-lab:进入新创建的目录。
  4. git init:在当前目录初始化一个新的 Git 仓库。
  5. echo "## Git Stash Lab" > README.md:创建一个名为 "README.md" 的新文件,内容为 "## Git Stash Lab"。
  6. git add README.md:将新文件添加到暂存区。
  7. git commit -m "Initial commit":使用暂存的更改创建你的第一个提交。

太棒了!我们现在有一个包含一次提交的仓库。让我们检查一下状态:

git status

你应该会看到一条消息,说明你的工作树是干净的(clean)。这意味着我们已经准备好开始实验 Git stash 了!

如果你遇到任何问题,请确保你处于正确的目录中,并且你的系统中已正确安装了 Git。你可以通过运行 git --version 来检查 Git 的安装情况。

储藏更改

现在工作区已经设置好了,让我们制造一些更改并学习如何储藏它们。

首先,让我们对 README.md 文件进行一些修改:

echo "This is a work in progress" >> README.md

此命令会在 README.md 文件末尾追加一行。我们再创建一个新文件:

echo "Some important notes" > notes.txt

现在,如果我们运行 git status,会看到既有已修改的文件,也有未跟踪的文件:

git status

你应该会看到输出显示 README.md 已修改,而 notes.txt 是未跟踪的(untracked)。

想象一下,此时你需要快速切换到另一个任务,但你还没准备好提交这些更改。这就是 git stash 派上用场的地方!

要储藏你的更改,请运行:

git stash

你应该会看到类似这样的输出:

Saved working directory and index state WIP on master: 1234567 Initial commit

现在,如果你再次运行 git status,你会发现一些有趣的现象:

git status

你会注意到,虽然 README.md 不再显示为已修改,但 notes.txt 仍然被列为未跟踪文件。这是关于 git stash 的一个关键点:

重要提示: 默认情况下,git stash 只会储藏:

  1. 对已跟踪文件(Git 已经在管理的文件)的更改
  2. 已暂存的更改

未跟踪的文件(比如我们的 notes.txt)默认不会包含在储藏中。这种行为是为了确保 Git 不会意外隐藏你可能不想包含在仓库中的新文件。

如果你想在储藏中包含未跟踪的文件,可以使用 -u(或 --include-untracked)选项:

git stash -u

运行此命令后,对 README.md 的更改和新的 notes.txt 文件都会被储藏起来。

要查看储藏库中的内容,可以使用:

git stash list

你应该会看到一到两个储藏条目,具体取决于你之前是否使用了 -u 选项。

q 键退出储藏列表视图。

请记住,储藏非常适合快速切换上下文。但是,它不能替代长期工作流中的提交。储藏应该是临时性的存储。

应用储藏的更改

既然我们已经储藏了更改,现在来学习如何将它们找回来。主要有两个命令可以实现这一点:git stash applygit stash pop

让我们从 git stash apply 开始:

git stash apply

运行此命令后,你可能会发现一些意想不到的情况。让我们检查一下状态:

git status

你应该会看到类似这样的输出:

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        notes.txt

nothing added to commit but untracked files present (use "git add" to track)

令人惊讶的是,你只能看到 notes.txt 作为一个未跟踪文件,而看不到 README.md 的任何更改。这种现象发生的原因是:

  1. 在步骤 2 中,我们首先使用了不带 -u 选项的 git stash,它只储藏了 README.md 的更改。
  2. 接着我们使用了 git stash -u,它储藏了未跟踪的 notes.txt 文件(此时 README.md 在上一次储藏后已经是干净的了)。
  3. 当我们应用储藏时,Git 默认应用最近的一次储藏(即使用 -u 创建的那次),其中只包含 notes.txt,因此你看不到 README.md 的更改。

要查看所有更改(包括 README.md 的更改),你可以指定储藏索引:

git stash apply stash@{1}

现在,如果你再次检查状态,你应该能看到 README.md 的更改以及作为未跟踪文件的 notes.txt。

这种情况凸显了使用储藏时的一个重要方面:创建和应用储藏的顺序会影响结果。在应用储藏之前检查其内容总是一个好习惯,尤其是在处理多个储藏时。

applypop 之间的区别在于:apply 会在你的工作区恢复更改,但同时保留储藏库中的记录;而 pop 会在应用更改后将其从储藏库中删除。

git stash clear
git stash -u
git stash list

我们先清除所有储藏以便重新开始,然后使用 -u 选项储藏更改以包含未跟踪文件。最后,列出储藏以验证储藏已创建。

让我们再次储藏更改并尝试 pop

git stash pop

你会看到与之前类似的输出,但如果你现在运行 git stash list,你会发现储藏库是空的。

为什么要同时拥有 applypop?当你想要将同一组储藏的更改应用到多个分支时,apply 非常有用。而当你只是想在同一个分支上恢复工作时,pop 更为常用。

从储藏创建分支

有时,你可能会意识到储藏的更改实际上应该放在独立的分支上。Git 通过 git stash branch 命令让这一切变得简单。

首先,让我们创建一些新更改并储藏它们:

echo "Feature in progress" >> README.md
echo "More notes" >> notes.txt
git stash -u

现在,让我们用这些更改创建一个新分支:

git stash branch feature-branch

这个命令会创建一个名为 "feature-branch" 的新分支,切换到该分支,然后将储藏的更改应用到该分支上。随后,该储藏会从储藏列表中移除。

你应该会看到类似这样的输出:

Switched to a new branch 'feature-branch'
On branch feature-branch
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:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        notes.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1234567890abcdef1234567890abcdef12345678)

当你储藏了一些实验性的更改,后来决定值得在独立的分支上继续开发时,这个功能特别有用。

请记住,从储藏创建分支后,如果你想保留这些更改,仍然需要提交它们:

git add README.md notes.txt
git commit -m "Start new feature"

要切换回你的 master 分支,请使用:

git checkout master

管理多个储藏

随着你对 Git 的深入使用,你可能会发现自己储藏了多组更改。Git 允许你轻松管理多个储藏。让我们探索如何创建、列出和管理多个储藏。

首先,让我们创建三个带有不同更改的储藏:

## 第一个储藏
echo "Change 1" >> README.md
git stash push -m "First change"

## 第二个储藏,包含未跟踪文件
echo "Change 2" >> README.md
echo "Note 2" >> notes.txt
git stash push -u -m "Second change"

## 第三个储藏
echo "Change 3" >> README.md
git stash push -m "Third change"

注意: 你会注意到我们现在使用的是 git stash push 而不仅仅是 git stashpush 子命令是创建储藏的现代且推荐的方式,尤其是当你想要使用 -m 标志添加自定义消息时。虽然 git stashgit stash -u 仍然有效(它们是 git stash pushgit stash push -u 的快捷方式),但显式使用 git stash push 可以提供更多的控制力和清晰度,特别是在通过描述性消息管理多个储藏时。

让我们分解一下我们做了什么:

  1. 创建了第一个储藏,修改了 README.md
  2. 创建了第二个储藏,既修改了 README.md 又包含了一个新的未跟踪文件。
  3. 创建了第三个储藏,再次修改了 README.md
  4. 使用 -m 标志添加了描述性消息。
  5. 在第二个储藏中使用了 -u 标志以包含未跟踪文件。

现在,让我们列出我们的储藏:

git stash list

你应该会看到类似这样的输出:

stash@{0}: On master: Third change
stash@{1}: On master: Second change
stash@{2}: On master: First change

你可以在不应用储藏的情况下检查其内容:

git stash show stash@{1}

如果想看更详细的内容,可以添加 -p 标志来查看完整的差异(diff):

git stash show -p stash@{1}

让我们再创建两个储藏,练习管理更大规模的更改集:

## 第四个储藏
echo "Change 4" >> README.md
git stash push -m "Fourth change"

## 第五个储藏
echo "Change 5" >> README.md
git stash push -m "Fifth change"

再次检查你的储藏列表:

git stash list

你现在应该在列表中看到五个储藏:

stash@{0}: On master: Fifth change
stash@{1}: On master: Fourth change
stash@{2}: On master: Third change
stash@{3}: On master: Second change
stash@{4}: On master: First change

当你同时处理多个任务时,管理多个储藏会非常有用。但是,尽量不要堆积太多的储藏,否则会变得混乱。对于长期工作,请考虑使用分支。

请记住:储藏旨在临时使用。如果你发现自己长期保留某些储藏,请考虑使用功能分支或直接提交更改。

清理储藏

随着你在工作流中使用储藏,你可能会积累一些不再需要的储藏。定期清理储藏以保持整洁是一个好习惯。

要移除单个储藏,可以使用我们之前见过的 drop 命令:

git stash drop stash@{2}

这会从我们的列表中移除第三个储藏(带有 "Third change" 的那个)。

如果你想一次性移除所有储藏,可以使用:

git stash clear

使用此命令要非常小心!它会移除所有储藏且无法撤销。

另一个有用的命令是 git stash pop,我们之前见过。它会应用最近的储藏,然后将其从储藏列表中移除:

git stash pop

请记住,保持储藏列表简短通常是一个好习惯。储藏是为正在进行的工作提供临时存储的。如果你发现自己积累了许多储藏,这可能是一个信号,表明你应该更频繁地提交更改,或者为长期工作创建功能分支。

总结

恭喜你,Git 储藏大师!你刚刚在 Git 工具箱中添加了一件强大的新工具。让我们回顾一下我们涵盖的关键概念:

  1. 储藏更改:你学习了如何使用 git stash 临时存储正在进行的工作。
  2. 应用储藏的更改:你发现了如何使用 git stash applygit stash pop 找回储藏的更改。
  3. 从储藏创建分支:你了解了如何通过 git stash branch 将一组储藏的更改转化为一个新分支。
  4. 管理多个储藏:你学习了如何处理多个储藏,根据需要应用和显示特定的储藏。
  5. 清理储藏:你通过学习如何移除单个储藏和清除所有储藏,练习了良好的储藏维护习惯。

Git stash 是一个极其有用的功能,它允许你在不提交半成品的情况下快速切换上下文。当你需要快速切换任务或分支时,它是完美的解决方案。

请记住,虽然储藏很有用,但它们应该是临时性的。对于长期工作,通常最好提交更改或创建新分支。明智地使用储藏,它们将帮助你保持工作流的顺畅和灵活。