分类 技术 下的文章

VeraCrypt 提供跨平台的开源文件加密功能。

 title=

许多年前,有一个名为 TrueCrypt 的加密软件。它的源码是可以得到的,尽管没有任何人声称曾对它进行过审计或贡献过。它的作者是(至今仍是)匿名的。不过,它是跨平台的,易于使用,而且真的非常有用。

TrueCrypt 允许你创建一个加密的文件“保险库”,在那里你可以存储任何类型的敏感信息(文本、音频、视频、图像、PDF 等)。只要你有正确的口令,TrueCrypt 就可以解密保险库,并在任何运行 TrueCrypt 的电脑上提供读写权限。这是一项有用的技术,它基本上提供了一个虚拟的、可移动的、完全加密的驱动器(除了文件以外),你可以在其中安全地存储你的数据。

TrueCrypt 最终关闭了,但一个名为 VeraCrypt 的替代项目迅速兴起,填补了这一空白。VeraCrypt 基于 TrueCrypt 7.1a,比原来的版本有许多改进(包括标准加密卷和引导卷的算法的重大变化)。在 VeraCrypt 1.12 及以后的版本中,你可以使用自定义迭代来提高加密安全性。更好的是,VeraCrypt 可以加载旧的 TrueCrypt 卷,所以如果你是 TrueCrypt 用户,可以很容易地将它们转移到 VeraCrypt 上。

安装 VeraCrypt

你可以从 VeraCrypt 下载页面 下载相应的安装文件,之后在所有主流平台上安装 VeraCrypt。

另外,你也可以自己从源码构建它。在 Linux 上,它需要 wxGTK3、makeself 和通常的开发栈(Binutils、GCC 等)。

当你安装后,从你的应用菜单中启动 VeraCrypt。

创建一个 VeraCrypt 卷

如果你刚接触 VeraCrypt,你必须先创建一个 VeraCrypt 加密卷(否则,你没有任何东西可以解密)。在 VeraCrypt 窗口中,点击左侧的 “Create Volume” 按钮。

 title=

在出现的 VeraCrypt 的卷创建向导窗口中,选择要创建一个加密文件容器还是要加密整个驱动器或分区。向导将为你的数据创建一个保险库,所以请按照提示进行操作。

在本文中,我创建了一个文件容器。VeraCrypt 容器和其他文件很像:它保存在硬盘、外置硬盘、云存储或其他任何你能想到的存储数据的地方。与其他文件一样,它可以被移动、复制和删除。与大多数其他文件不同的是,它可以\_容纳\_更多的文件,这就是为什么我认为它是一个“保险库”,而 VeraCrypt 开发者将其称为“容器”。它的开发者将 VeraCrypt 文件称为“容器”,是因为它可以包含其他数据对象;它与 LXC、Kubernetes 和其他现代 IT 机制所流行的容器技术无关。

选择一个文件系统

在创建卷的过程中,你会被要求选择一个文件系统来决定你放在保险库中的文件的存储方式。微软 FAT 格式是过时的、非日志型,并且限制了卷和文件的大小,但它是所有平台都能读写的一种格式。如果你打算让你的 VeraCrypt 保险库跨平台,FAT 是你最好的选择。

除此之外,NTFS 适用于 Windows 和 Linux。开源的 EXT 系列适用于 Linux。

挂载 VeraCrypt 加密卷

当你创建了 VeraCrypt 卷,你就可以在 VeraCrypt 窗口中加载它。要挂载一个加密库,点击右侧的 “Select File” 按钮。选择你的加密文件,选择 VeraCrypt 窗口上半部分的一个编号栏,然后点击位于 VeraCrypt 窗口左下角的 “Mount” 按钮。

你挂载的卷在 VeraCrypt 窗口的可用卷列表中,你可以通过文件管理器访问该卷,就像访问一个外部驱动器一样。例如,在 KDE 上,我打开 Dolphin,进入 /media/veracrypt1,然后我就可以把文件复制到我的保险库里。

只要你的设备上有 VeraCrypt,你就可以随时访问你的保险库。在你手动在 VeraCrypt 中挂载之前,文件都是加密的,在那里,文件会保持解密,直到你再次关闭卷。

关闭 VeraCrypt 卷

为了保证你的数据安全,当你不需要打开 VeraCrypt 卷时,关闭它是很重要的。这样可以保证数据的安全,不被人窥视,且不被人趁机犯罪。

 title=

关闭 VeraCrypt 容器和打开容器一样简单。在 VeraCrypt 窗口中选择列出的卷,然后点击 “Dismount”。你就不能访问保险库中的文件了,其他人也不会再有访问权。

VeraCrypt 轻松实现跨平台加密

有很多方法可以保证你的数据安全,VeraCrypt 试图为你提供方便,而无论你需要在什么平台上使用这些数据。如果你想体验简单、开源的文件加密,请尝试 VeraCrypt。


via: https://opensource.com/article/21/4/open-source-encryption

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

获得自由尝试的权利,同时在你的实验出错时可以安全地拥有一个新的、链接的克隆存储库。

 title=

Git 的设计部分是为了进行实验。如果你知道你的工作会被安全地跟踪,并且在出现严重错误时有安全状态存在,你就不会害怕尝试新的想法。不过,创新的部分代价是,你很可能会在这个过程中弄得一团糟。文件会被重新命名、移动、删除、更改、切割成碎片;新的文件被引入;你不打算跟踪的临时文件会在你的工作目录中占据一席之地等等。

简而言之,你的工作空间变成了纸牌屋,在“快好了!”和“哦,不,我做了什么?”之间岌岌可危地平衡着。那么,当你需要把仓库恢复到下午的一个已知状态,以便完成一些真正的工作时,该怎么办?我立刻想到了 git branchgit stash 这两个经典命令,但这两个命令都不是用来处理未被跟踪的文件的,而且文件路径的改变和其他重大的转变也会让人困惑,它们只能把工作暂存(stash)起来以备后用。解决这个需求的答案是 Git 工作树。

什么是 Git 工作树

Git 工作树 worktree 是 Git 仓库的一个链接副本,允许你同时签出多个分支。工作树与主工作副本的路径是分开的,它可以处于不同的状态和不同的分支上。在 Git 中新建工作树的好处是,你可以在不干扰当前工作环境的情况下,做出与当前任务无关的修改、提交修改,然后在以后合并。

直接从 git-worktree 手册中找到了一个典型的例子:当你正在为一个项目做一个令人兴奋的新功能时,你的项目经理告诉你有一个紧急的修复工作。问题是你的工作仓库(你的“工作树”)处于混乱状态,因为你正在开发一个重要的新功能。你不想在当前的冲刺中“偷偷地”进行修复,而且你也不愿意把变更暂存起来,为修复创建一个新的分支。相反,你决定创建一个新的工作树,这样你就可以在那里进行修复:

$ git branch | tee
* dev
trunk
$ git worktree add -b hotfix ~/code/hotfix trunk
Preparing ../hotfix (identifier hotfix)
HEAD is now at 62a2daf commit

在你的 code 目录中,你现在有一个新的目录叫做 hotfix,它是一个与你的主项目仓库相连的 Git 工作树,它的 HEAD 停在叫做 trunk 的分支上。现在你可以把这个工作树当作你的主工作区来对待。你可以把目录切换到它里面,进行紧急修复、提交、并最终删除这个工作树:

$ cd ~/code/hotfix
$ sed -i 's/teh/the/' hello.txt
$ git commit --all --message 'urgent hot fix'

一旦你完成了你的紧急工作,你就可以回到你之前的任务。你可以控制你的热修复何时被集成到主项目中。例如,你可以直接将变更从其工作树推送到项目的远程存储库中:

$ git push origin HEAD
$ cd ~/code/myproject

或者你可以将工作树存档为 TAR 或 ZIP 文件:

$ cd ~/code/myproject
$ git archive --format tar --output hotfix.tar master

或者你可以从单独的工作树中获取本地的变化:

$ git worktree list
/home/seth/code/myproject  15fca84 [dev]
/home/seth/code/hotfix     09e585d [master]

从那里,你可以使用任何最适合你和你的团队的策略合并你的变化。

列出活动工作树

你可以使用 git worktree list 命令获得工作树的列表,并查看每个工作树签出的分支:

$ git worktree list
/home/seth/code/myproject  15fca84 [dev]
/home/seth/code/hotfix     09e585d [master]

你可以在任何一个工作树中使用这个功能。工作树始终是连接的(除非你手动移动它们,破坏 Git 定位工作树的能力,从而切断连接)。

移动工作树

Git 会跟踪项目 .git 目录下工作树的位置和状态:

$ cat ~/code/myproject/.git/worktrees/hotfix/gitdir
/home/seth/code/hotfix/.git

如果你需要重定位一个工作树,必须使用 git worktree move;否则,当 Git 试图更新工作树的状态时,就会失败:

$ mkdir ~/Temp
$ git worktree move hotfix ~/Temp
$ git worktree list
/home/seth/code/myproject  15fca84 [dev]
/home/seth/Temp/hotfix     09e585d [master]

移除工作树

当你完成你的工作时,你可以用 remove 子命令删除它:

$ git worktree remove hotfix
$ git worktree list
/home/seth/code/myproject  15fca84 [dev]

为了确保你的 .git 目录是干净的,在删除工作树后使用 prune 子命令:

$ git worktree remove prune

何时使用工作树

与许多选项一样,无论是标签还是书签还是自动备份,都要靠你来跟踪你产生的数据,否则可能会变得不堪重负。不要经常使用工作树,要不你最终会有 20 份存储库的副本,每份副本的状态都略有不同。我发现最好是创建一个工作树,做需要它的任务,提交工作,然后删除树。保持简单和专注。

重要的是,工作树为你管理 Git 存储库的方式提供了更好的灵活性。在需要的时候使用它们,再也不用为了检查另一个分支上的内容而争先恐后地保存工作状态了。


via: https://opensource.com/article/21/4/git-worktree

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用开源工具来保护你的 Linux 环境不被入侵。

 title=

如今我们的许多个人和专业数据都可以在网上获得,因此无论是专业人士还是普通互联网用户,学习安全和隐私的基本知识是非常重要的。作为一名学生,我通过学校的 CyberPatriot 活动获得了这方面的经验,在那里我有机会与行业专家交流,了解网络漏洞和建立系统安全的基本步骤。

本文基于我作为初学者迄今所学的知识,详细介绍了六个简单的步骤,以提高个人使用的 Linux 环境的安全性。在我的整个旅程中,我利用开源工具来加速我的学习过程,并熟悉了与提升 Linux 服务器安全有关的更高层次的概念。

我使用我最熟悉的 Ubuntu 18.04 版本测试了这些步骤,但这些步骤也适用于其他 Linux 发行版。

1、运行更新

开发者们不断地寻找方法,通过修补已知的漏洞,使服务器更加稳定、快速、安全。定期运行更新是一个好习惯,可以最大限度地提高安全性。运行它们:

sudo apt-get update && apt-get upgrade

2、启用防火墙保护

启用防火墙 可以更容易地控制服务器上的进站和出站流量。在 Linux 上有许多防火墙应用程序可以使用,包括 firewall-cmd 简单防火墙 Uncomplicated Firewall UFW)。我使用 UFW,所以我的例子是专门针对它的,但这些原则适用于你选择的任何防火墙。

安装 UFW:

sudo apt-get install ufw

如果你想进一步保护你的服务器,你可以拒绝传入和传出的连接。请注意,这将切断你的服务器与世界的联系,所以一旦你封锁了所有的流量,你必须指定哪些出站连接是允许从你的系统中发出的:

sudo ufw default deny incoming
sudo ufw default allow outgoing

你也可以编写规则来允许你个人使用所需要的传入连接:

ufw allow <service>

例如,允许 SSH 连接:

ufw allow ssh

最后,启用你的防火墙:

sudo ufw enable

3、加强密码保护

实施强有力的密码政策是保持服务器安全、防止网络攻击和数据泄露的一个重要方面。密码策略的一些最佳实践包括强制要求最小长度和指定密码年龄。我使用 libpam-cracklib 软件包来完成这些任务。

安装 libpam-cracklib 软件包:

sudo apt-get install libpam-cracklib

强制要求密码的长度:

  • 打开 /etc/pam.d/common-password 文件。
  • minlen=12 行改为你需要的任意字符数,从而改变所有密码的最小字符长度要求。

为防止密码重复使用:

  • 在同一个文件(/etc/pam.d/common-password)中,添加 remember=x 行。
  • 例如,如果你想防止用户重复使用他们最后 5 个密码中的一个,使用 remember=5

要强制要求密码年龄:

  • /etc/login.defs 文件中找到以下几行,并用你喜欢的时间(天数)替换。例如:
PASS_MIN_AGE: 3
PASS_MAX_AGE: 90
PASS_WARN_AGE: 14 

强制要求字符规格:

  • 在密码中强制要求字符规格的四个参数是 lcredit(小写)、ucredit(大写)、dcredit(数字)和 ocredit(其他字符)。
  • 在同一个文件(/etc/pam.d/common-password)中,找到包含 pam_cracklib.so 的行。

    • 在该行末尾添加以下内容:lcredit=-a ucredit=-b dcredit=-c ocredit=-d
    • 例如,下面这行要求密码必须至少包含一个每种字符。你可以根据你喜欢的密码安全级别来改变数字。lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1

4、停用容易被利用的非必要服务。

停用不必要的服务是一种最好的做法。这样可以减少开放的端口,以便被利用。

安装 systemd 软件包:

sudo apt-get install systemd

查看哪些服务正在运行:

systemctl list-units

识别 哪些服务可能会导致你的系统出现潜在的漏洞。对于每个服务可以:

  • 停止当前正在运行的服务:systemctl stop <service>
  • 禁止服务在系统启动时启动:systemctl disable <service>
  • 运行这些命令后,检查服务的状态:systemctl status <service>

5、检查监听端口

开放的端口可能会带来安全风险,所以检查服务器上的监听端口很重要。我使用 netstat 命令来显示所有的网络连接:

netstat -tulpn

查看 “address” 列,确定 端口号。一旦你找到了开放的端口,检查它们是否都是必要的。如果不是,调整你正在运行的服务,或者调整你的防火墙设置。

6、扫描恶意软件

杀毒扫描软件可以有用的防止病毒进入你的系统。使用它们是一种简单的方法,可以让你的服务器免受恶意软件的侵害。我首选的工具是开源软件 ClamAV

安装 ClamAV:

sudo apt-get install clamav

更新病毒签名:

sudo freshclam

扫描所有文件,并打印出被感染的文件,发现一个就会响铃:

sudo clamscan -r --bell -i /

你可以而且应该设置为自动扫描,这样你就不必记住或花时间手动进行扫描。对于这样简单的自动化,你可以使用 systemd 定时器 或者你的 喜欢的 cron 来做到。

保证你的服务器安全

我们不能把保护服务器安全的责任只交给一个人或一个组织。随着威胁环境的不断迅速扩大,我们每个人都应该意识到服务器安全的重要性,并采用一些简单、有效的安全最佳实践。

这些只是你提升 Linux 服务器的安全可以采取的众多步骤中的一部分。当然,预防只是解决方案的一部分。这些策略应该与严格监控拒绝服务攻击、用 Lynis 做系统分析以及创建频繁的备份相结合。

你使用哪些开源工具来保证服务器的安全?在评论中告诉我们它们的情况。


via: https://opensource.com/article/21/4/securing-linux-servers

作者:Sahana Sreeram 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 Linux 统一密钥设置(LUKS)为物理驱动器或云存储上的敏感文件创建一个加密保险库。

 title=

最近,我演示了如何在 Linux 上使用 统一密钥设置 Linux Unified Key Setup LUKS)和 cryptsetup 命令 实现全盘加密。虽然加密整个硬盘在很多情况下是有用的,但也有一些原因让你不想对整个硬盘进行加密。例如,你可能需要让一个硬盘在多个平台上工作,其中一些平台可能没有集成 LUKS。此外,现在是 21 世纪,由于云的存在,你可能不会使用物理硬盘来处理所有的数据。

几年前,有一个名为 TrueCrypt 的系统,允许用户创建加密的文件保险库,可以通过 TrueCrypt 解密来提供读/写访问。这是一项有用的技术,基本上提供了一个虚拟的便携式、完全加密的驱动器,你可以在那里存储重要数据。TrueCrypt 项目关闭了,但它可以作为一个有趣的模型。

幸运的是,LUKS 是一个灵活的系统,你可以使用它和 cryptsetup 在一个独立的文件中创建一个加密保险库,你可以将其保存在物理驱动器或云存储中。

下面就来介绍一下怎么做。

1、建立一个空文件

首先,你必须创建一个预定大小的空文件。就像是一种保险库或保险箱,你可以在其中存储其他文件。你使用的命令是 util-linux 软件包中的 fallocate

$ fallocate --length 512M vaultfile.img

这个例子创建了一个 512MB 的文件,但你可以把你的文件做成任何你想要的大小。

2、创建一个 LUKS 卷

接下来,在空文件中创建一个 LUKS 卷:

$ cryptsetup --verify-passphrase \
    luksFormat vaultfile.img

3、打开 LUKS 卷

要想创建一个可以存储文件的文件系统,必须先打开 LUKS 卷,并将其挂载到电脑上:

$ sudo cryptsetup open \
    --type luks vaultfile.img myvault
$ ls /dev/mapper
myvault

4、建立一个文件系统

在你打开的保险库中建立一个文件系统:

$ sudo mkfs.ext4 -L myvault /dev/mapper/myvault

如果你现在不需要它做什么,你可以关闭它:

$ sudo cryptsetup close myvault

5、开始使用你的加密保险库

现在一切都设置好了,你可以在任何需要存储或访问私人数据的时候使用你的加密文件库。要访问你的保险库,必须将其挂载为一个可用的文件系统:

$ sudo cryptsetup open \
    --type luks vaultfile.img myvault
$ ls /dev/mapper
myvault
$ sudo mkdir /myvault
$ sudo mount /dev/mapper/myvault /myvault

这个例子用 cryptsetup 打开保险库,然后把保险库从 /dev/mapper 下挂载到一个叫 /myvault 的新目录。和 Linux 上的任何卷一样,你可以把 LUKS 卷挂载到任何你想挂载的地方,所以除了 /myvault,你可以用 /mnt~/myvault 或任何你喜欢的位置。

当它被挂载后,你的 LUKS 卷就会被解密。你可以像读取和写入文件一样读取和写入它,就像它是一个物理驱动器一样。

当使用完你的加密保险库时,请卸载并关闭它:

$ sudo umount /myvault
$ sudo cryptsetup close myvault

加密的文件保险库

你用 LUKS 加密的镜像文件和其他文件一样,都是可移动的,因此你可以将你的保险库存储在硬盘、外置硬盘,甚至是互联网上。只要你可以使用 LUKS,就可以解密、挂载和使用它来保证你的数据安全。轻松加密,提高数据安全性,不妨一试。


via: https://opensource.com/article/21/4/linux-encryption

作者:Seth Kenlon 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

了解 git cherry-pick 命令是什么,为什么用以及如何使用。

 title=

当你和一群程序员一起工作时,无论项目大小,处理多个 Git 分支之间的变更都会变得很困难。有时,你不想将整个 Git 分支合并到另一个分支,而是想选择并移动几个特定的提交。这个过程被称为 “ 遴选 cherry-pick ”。

本文将介绍“遴选”是什么、为何使用以及如何使用。

那么让我们开始吧。

什么是遴选?

使用遴选(cherry-pick)命令,Git 可以让你将任何分支中的个别提交合并到你当前的 Git HEAD 分支中。

当执行 git merge 或者 git rebase 时,一个分支的所有提交都会被合并。cherry-pick 命令允许你选择单个提交进行整合。

遴选的好处

下面的情况可能会让你更容易理解遴选功能。

想象一下,你正在为即将到来的每周冲刺实现新功能。当你的代码准备好了,你会把它推送到远程分支,准备进行测试。

然而,客户并不是对所有修改都满意,要求你只呈现某些修改。因为客户还没有批准下次发布的所有修改,所以 git rebase 不会有预期的结果。为什么会这样?因为 git rebase 或者 git merge 会把上一个冲刺的每一个调整都纳入其中。

遴选就是答案!因为它只关注在提交中添加的变更,所以遴选只会带入批准的变更,而不添加其他的提交。

还有其他几个原因可以使用遴选:

  • 这对于 bug 修复是必不可少的,因为 bug 是出现在开发分支中对应的提交的。
  • 你可以通过使用 git cherry-pick 来避免不必要的工作,而不用使用其他选项例如 git diff 来应用特定变更。
  • 如果因为不同 Git 分支的版本不兼容而无法将整个分支联合起来,那么它是一个很有用的工具。

使用 cherry-pick 命令

cherry-pick 命令的最简单形式中,你只需使用 SHA 标识符来表示你想整合到当前 HEAD 分支的提交。

要获得提交的哈希值,可以使用 git log 命令:

$ git log --oneline

当你知道了提交的哈希值后,你就可以使用 cherry-pick 命令。

语法是:

$ git cherry-pick <commit sha>

例如:

$ git cherry-pick 65be1e5

这将会把指定的修改合并到当前已签出的分支上。

如果你想做进一步的修改,也可以让 Git 将提交的变更内容添加到你的工作副本中。

语法是:

$ git cherry-pick <commit sha> --no-commit

例如:

$ git cherry-pick 65be1e5 --no-commit

如果你想同时选择多个提交,请将它们的提交哈希值用空格隔开:

$ git cherry-pick hash1 hash3

当遴选提交时,你不能使用 git pull 命令,因为它能获取一个仓库的提交自动合并到另一个仓库。cherry-pick 是一个专门不这么做的工具;另一方面,你可以使用 git fetch,它可以获取提交,但不应用它们。毫无疑问,git pull 很方便,但它不精确。

自己尝试

要尝试这个过程,启动终端并生成一个示例项目:

$ mkdir fruit.git
$ cd fruit.git
$ git init .

创建一些数据并提交:

$ echo "Kiwifruit" > fruit.txt
$ git add fruit.txt
$ git commit -m 'First commit'

现在,通过创建一个项目的复刻来代表一个远程开发者:

$ mkdir ~/fruit.fork
$ cd !$
$ echo "Strawberry" >> fruit.txt
$ git add fruit.txt
$ git commit -m 'Added a fruit"

这是一个有效的提交。现在,创建一个不好的提交,代表你不想合并到你的项目中的东西:

$ echo "Rhubarb" >> fruit.txt
$ git add fruit.txt
$ git commit -m 'Added a vegetable that tastes like a fruit"

返回你的仓库,从你的假想的开发者那里获取提交的内容:

$ cd ~/fruit.git
$ git remote add dev ~/fruit.fork
$ git fetch dev
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done...
$ git log –oneline dev/master
e858ab2 Added a vegetable that tastes like a fruit
0664292 Added a fruit
b56e0f8 First commit

你已经从你想象中的开发者那里获取了提交的内容,但你还没有将它们合并到你的版本库中。你想接受第二个提交,但不想接受第三个提交,所以使用 cherry-pick

$ git cherry-pick 0664292

第二次提交现在在你的仓库里了:

$ cat fruit.txt
Kiwifruit
Strawberry

将你的更改推送到远程服务器上,这就完成了!

避免使用遴选的原因

在开发者社区中,通常不鼓励所以遴选。主要原因是它会造成重复提交,而你也失去了跟踪你的提交历史的能力。

如果你不按顺序地遴选了大量的提交,这些提交会被记录在你的分支中,这可能会在 Git 分支中导致不理想的结果。

遴选是一个强大的命令,如果没有正确理解可能发生的情况,它可能会导致问题。不过,当你搞砸了,提交到错误的分支时,它可能会救你一命(至少是你当天的工作)。


via: https://opensource.com/article/21/4/cherry-picking-git

作者:Rajeev Bera 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

学习如何使用 git stash 命令,以及何时应该使用它。

 title=

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

Linus Torvalds 在 2005 年创建了 Git 用于开发 Linux 内核。本文将介绍 git stash 命令,并探讨一些有用的暂存变更的选项。本文假定你对 Git 概念 有基本的了解,并对工作树、暂存区和相关命令有良好的理解。

为什么 git stash 很重要?

首先要明白为什么在 Git 中暂存变更很重要。假设 Git 没有暂存变更的命令。当你正在一个有两个分支(A 和 B)的仓库上工作时,这两个分支已经分叉了一段时间,并且有不同的头。当你正在处理 A 分支的一些文件时,你的团队要求你修复 B 分支的一个错误。你迅速将你的修改保存到 A 分支(但没有提交),并尝试用 git checkout B 来签出 B 分支。Git 会立即中止了这个操作,并抛出错误:“你对以下文件的本地修改会被该签出覆盖……请在切换分支之前提交你的修改或将它们暂存起来。”

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

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

第二种方法是个馊主意。第一种方法虽然看起来很传统,但却不太灵活,因为保存未完成工作的修改会被当作一个检查点,而不是一个仍在进行中的补丁。这正是设计 git stash 的场景。

git stash 将未提交的改动保存在本地,让你可以进行修改、切换分支以及其他 Git 操作。然后,当你需要的时候,你可以重新应用这些存储的改动。暂存是本地范围的,不会被 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),并允许你在需要时检索这些修改。当你需要在不同的上下文之间切换时,它很方便。它允许你保存以后可能需要的更改,是让你的工作目录干净同时保持更改完整的最快方法。

如何创建一个暂存

暂存你的变化的最简单的命令是 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 --includ-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,?]?

列出你的暂存

你可以用 git stash list 命令查看你的暂存。暂存是后进先出(LIFO)方式保存的:

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

默认情况下,暂存会显示在你创建它的分支和提交的顶部,被标记为 WIP。然而,当你有多个暂存时,这种有限的信息量并没有帮助,因为很难记住或单独检查它们的内容。要为暂存添加描述,可以使用命令 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@{0})中的改动。apply 会重新应用变更;而 pop 则会将暂存的变更重新应用到工作副本中,并从暂存中删除。如果你不需要再次重新应用被暂存的更改,则首选 pop

你可以通过传递标识符作为最后一个参数来选择你想要弹出或应用的储藏:

$ git stash pop stash@{1}

$ git stash apply stash@{1}

清理暂存

删除不再需要的暂存是好的习惯。你必须用以下命令手动完成:

  • git stash clear 通过删除所有的暂存库来清空该列表。
  • git stash drop <stash_id> 从暂存列表中删除一个特定的暂存。

检查暂存的差异

命令 git stash show <stash_id> 允许你查看一个暂存的差异:

$ 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 +-

要获得更详细的差异,需要传递 --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&lt;IAppNavHeaderProps&gt;{
  render()

签出到新的分支

你可能会遇到这样的情况:一个分支和你的暂存中的变更有分歧,当你试图重新应用暂存时,会造成冲突。一个简单的解决方法是使用 git stash branch <new_branch_name stash_id> 命令,它将根据创建暂存时的提交创建一个新分支,并将暂存中的修改弹出:

$ 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)

在不打扰暂存参考日志的情况下进行暂存

在极少数情况下,你可能需要创建一个暂存,同时保持暂存参考日志(reflog)的完整性。这些情况可能出现在你需要一个脚本作为一个实现细节来暂存的时候。这可以通过 git stash create 命令来实现;它创建了一个暂存条目,并返回它的对象名,而不将其推送到暂存参考日志中:

$ git stash create "sample stash"
63a711cd3c7f8047662007490723e26ae9d4acf9

有时,你可能会决定将通过 git stash create 创建的暂存条目推送到暂存参考日志:

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

结论

我希望你觉得这篇文章很有用,并学到了新的东西。如果我遗漏了任何有用的使用暂存的选项,请在评论中告诉我。


via: https://opensource.com/article/21/4/git-stash

作者:Ramakrishna Pattnaik 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出