git stash 命令的实用指南

了解如何使用 git stash 命令以及何时应该使用它。
110 位读者喜欢这篇文章。
woman on laptop sitting at the window

CC BY 3.0 US Mapbox Uncharted ERG

版本控制是软件开发人员日常生活中不可分割的一部分。很难想象有任何团队在不使用版本控制工具的情况下开发软件。同样难以想象有任何开发人员没有使用过(或至少听说过)Git。在 2018 年 Stackoverflow 开发者调查中,74,298 名参与者中有 87.2% 使用 Git 进行版本控制。

Linus Torvalds 于 2005 年创建了 Git,用于开发 Linux 内核。本文介绍了 git stash 命令,并探讨了隐藏更改的一些有用选项。本文假设您对 Git 概念有基本的了解,并且对工作区、暂存区和相关命令有很好的理解。

为什么 git stash 很重要?

首先要理解的是为什么在 Git 中隐藏更改很重要。假设 Git 没有隐藏更改的命令。假设您正在处理一个具有两个分支 A 和 B 的存储库。A 和 B 分支已经分叉了很长时间,并且具有不同的头部。在处理 A 分支中的一些文件时,您的团队要求您修复 B 分支中的一个错误。您快速保存对 A 的更改,并尝试使用 git checkout B 检出 B 分支。Git 立即中止操作并抛出错误“您对以下文件的本地更改将被检出覆盖……请提交您的更改或在切换分支之前将它们隐藏起来。”

在这种情况下,有几种方法可以启用分支切换

  • 在 A 分支中的该点创建一个提交,提交并推送您的更改以修复 B 中的错误,然后再次检出 A 并运行 git reset HEAD^ 以恢复您的更改。
  • 手动保留 Git 未跟踪的文件中的更改。

第二种方法是一个坏主意。第一种方法虽然看起来很传统,但灵活性较差,因为未完成的已保存更改被视为检查点,而不是仍在进行中的补丁。这正是 git stash 设计的场景。

Git stash 在本地保存未提交的更改,允许您进行更改、切换分支和执行其他 Git 操作。然后,您可以在需要时重新应用隐藏的更改。stash 是本地作用域的,不会通过 git push 推送到远程。

如何使用 git stash

以下是使用 git stash 时要遵循的顺序

  1. 将更改保存到 A 分支。
  2. 运行 git stash
  3. 检出 B 分支。
  4. 修复 B 分支中的错误。
  5. 提交并(可选)推送到远程。
  6. 检出 A 分支
  7. 运行 git stash pop 以恢复您隐藏的更改。

Git stash 将您对工作目录所做的更改本地存储(在您项目的 .git 目录中;准确地说是 /.git/refs/stash),并允许您在需要时检索这些更改。当您需要在上下文之间切换时,这很方便。它允许您保存稍后可能需要的更改,并且是在保持更改完整的同时清理工作目录的最快方法。

如何创建 stash

隐藏更改的最简单命令是 git stash

$ git stash
Saved working directory and index state WIP on master; d7435644 Feat: configure graphql endpoint

默认情况下,git stash 存储(或“隐藏”)未提交的更改(已暂存和未暂存的文件),并忽略未跟踪和忽略的文件。通常,您不需要隐藏未跟踪和忽略的文件,但有时它们可能会干扰您想在代码库中执行的其他操作。

您可以使用其他选项让 git stash 处理未跟踪和忽略的文件

  • git stash -ugit stash --include-untracked 隐藏未跟踪的文件。
  • git stash -agit stash --all 隐藏未跟踪的文件和忽略的文件。

要隐藏特定文件,您可以使用命令 git stash -pgit stash –patch

$ git stash --patch
diff --git a/.gitignore b/.gitignore
index 32174593..8d81be6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 # dependencies
 node_modules/
 /.pnp
+f,fmfm
 .pnp.js

 # testing
(1/1) Stash this hunk [y,n,q,a,d,e,?]?

列出您的 stashes

您可以使用命令 git stash list 查看您的 stashes。Stashes 以后进先出 (LIFO) 的方式保存

$ git stash list
stash@{0}: WIP on master: d7435644 Feat: configure graphql endpoint

默认情况下,stashes 被标记为 WIP,位于您创建 stash 的分支和提交的顶部。但是,当您有多个 stash 时,这种有限的信息没有帮助,因为很难记住或单独检查它们的内容。要向 stash 添加描述,您可以使用命令 git stash save <description>

$ git stash save "remove semi-colon from schema"
Saved working directory and index state On master: remove semi-colon from schema

$ git stash list
stash@{0}: On master: remove semi-colon from schema
stash@{1}: WIP on master: d7435644 Feat: configure graphql endpoint

检索隐藏的更改

您可以使用命令 git stash applygit stash pop 重新应用隐藏的更改。这两个命令都会重新应用隐藏在最新 stash 中的更改(即 stash@{0})。stash 重新应用更改,而 pop 从 stash 中删除更改并将它们重新应用到工作副本。如果您不需要将隐藏的更改重新应用多次,则首选 pop。

您可以通过将标识符作为最后一个参数传递来选择要 pop 或 apply 的 stash

$ git stash pop stash@{1} 

或者

$ git stash apply stash@{1}

清理 stash

删除不再需要的 stashes 是一个好习惯。您必须使用以下命令手动执行此操作

  • git stash clear 通过删除所有 stashes 来清空 stash 列表。
  • git stash drop <stash_id> 从 stash 列表中删除特定的 stash。

检查 stash diffs

命令 git stash show <stash_id> 允许您查看 stash 的 diff

$ git stash show stash@{1}
console/console-init/ui/.graphqlrc.yml        |   4 +-
console/console-init/ui/generated-frontend.ts | 742 +++++++++---------
console/console-init/ui/package.json          |   2 +-

要获得更详细的 diff,请传递 --patch-p 标志

$ git stash show stash@{0} --patch
diff --git a/console/console-init/ui/package.json b/console/console-init/ui/package.json
index 755912b97..5b5af1bd6 100644
--- a/console/console-init/ui/package.json
+++ b/console/console-init/ui/package.json
@@ -1,5 +1,5 @@
 {
- "name": "my-usepatternfly",
+ "name": "my-usepatternfly-2",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:4000"
diff --git a/console/console-init/ui/src/AppNavHeader.tsx b/console/console-init/ui/src/AppNavHeader.tsx
index a4764d2f3..da72b7e2b 100644
--- a/console/console-init/ui/src/AppNavHeader.tsx
+++ b/console/console-init/ui/src/AppNavHeader.tsx
@@ -9,8 +9,8 @@ import { css } from "@patternfly/react-styles";

interface IAppNavHeaderProps extends PageHeaderProps {
- toolbar?: React.ReactNode;
- avatar?: React.ReactNode;
+ toolbar?: React.ReactNode;
+ avatar?: React.ReactNode;
}

export class AppNavHeader extends React.Component<IAppNavHeaderProps>{
  render()

检出到新分支

您可能会遇到这样一种情况:一个分支中的更改和您的 stash 发散,导致您尝试重新应用 stash 时发生冲突。对此的一个干净的修复方法是使用命令 git stash branch <new_branch_name stash_id>,它基于创建 stash *from* 的提交创建一个新分支,并将隐藏的更改 pop 到该分支

$ git stash branch test_2 stash@{0}
Switched to a new branch 'test_2'
On branch test_2
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: .graphqlrc.yml
modified: generated-frontend.ts
modified: package.json
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (fe4bf8f79175b8fbd3df3c4558249834ecb75cd1)

隐藏而不干扰 stash reflog

在极少数情况下,您可能需要在保持 stash 引用日志 (reflog) 完整的情况下创建一个 stash。当您需要一个脚本来隐藏作为实现细节时,可能会出现这些情况。这可以通过 git stash create 命令来实现;它创建一个 stash 条目并返回其对象名称,而不会将其推送到 stash reflog

$ git stash create "sample stash" 
63a711cd3c7f8047662007490723e26ae9d4acf9

有时,您可能会决定将通过 git stash create 创建的 stash 条目推送到 stash reflog

$ git stash store -m "sample stash testing.." "63a711cd3c7f8047662007490723e26ae9d4acf9"
$ git stash list
stash @{0}: sample stash testing..

结论

我希望您发现这篇文章有用并学到了一些新东西。如果我遗漏了任何使用 stash 的有用选项,请在评论中告诉我。

接下来要阅读的内容

Git 的 10 个优点

更多地了解 Git 的工作原理可以更容易地使用 Git。在我们的读者最喜欢的年度 Git 文章中了解更多信息。

标签
Ramakrishna Pattnaik
Ramakrishna Pattnaik 是一位来自 Bhubaneswar 的 Web 开发人员,目前在班加罗尔的 Red Hat Middleware 团队担任助理软件工程师。一位开源爱好者和贡献者。喜欢小说。

评论已关闭。

Creative Commons License本作品采用 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.