2018年4月

字体可帮助你通过设计以创意的方式表达你的想法。无论给图片加标题、编写演示文稿,还是设计问候语或广告,字体都可以将你的想法提升到更高水平。很容易仅仅为了它们的审美品质而爱上它们。幸运的是,Fedora 使安装字体变得简单。以下是如何做的。

全系统安装

如果你在系统范围内安装字体,那么它可以让所有用户使用。此方式的最佳方法是使用官方软件库中的 RPM 软件包。

开始前打开 Fedora Workstation 中的 “Software” 工具,或者其他使用官方仓库的工具。选择横栏中选择 “Add-ons” 类别。接着在该类别中选择 “Fonts”。你会看到类似于下面截图中的可用字体:

当你选择一种字体时,会出现一些细节。根据几种情况,你可能能够预览字体的一些示例文本。点击 “Install” 按钮将其添加到你的系统。根据系统速度和网络带宽,完成此过程可能需要一些时间。

你还可以在字体细节中通过 “Remove” 按钮删除前面带有勾的已经安装的字体。

个人安装

如果你以兼容格式:.ttf、 otf 、.ttc、.pfa 、.pfb 或者 .pcf 下载了字体,则此方法效果更好。这些字体扩展名不应通过将它们放入系统文件夹来安装在系统范围内。这种类型的非打包字体不能自动更新。它们也可能会在稍后干扰一些软件操作。安装这些字体的最佳方法是安装在你自己的个人数据目录中。

打开 Fedora Workstation 中的 “Files” 应用或你选择的类似文件管理器应用。如果你使用 “Files”,那么可能需要使用 Ctrl+H 组合键来显示隐藏的文件和文件夹。查找 .fonts 文件夹并将其打开。如果你没有 .fonts 文件夹,请创建它。 (记住最前面的点并全部使用小写。)

将已下载的字体文件复制到 .fonts 文件夹中。此时你可以关闭文件管理器。打开一个终端并输入以下命令:

fc-cache

这将重建字体缓存,帮助 Fedora 可以找到并引用它。你可能还需要重新启动需要使用新字体的应用程序,例如 Inkscape 或 LibreOffice。你重新启动后,新的字体应该就可以使用了。


照片由 Raphael Schaller 发布在 Unsplash 中。


作者简介:

Paul W. Frields 自 1997 年以来一直是 Linux 用户和爱好者,并于 2003 年 Fedora 发布不久后加入项目。他是 Fedora 项目委员会的创始成员之一,并从事文档、网站发布、倡导、工具链开发和维护软件工作。他于 2008 年 2 月至 2010 年 7 月在红帽担任 Fedora 项目负责人,现任红帽公司工程部经理。他目前和他的妻子和两个孩子一起住在弗吉尼亚州。


via: https://fedoramagazine.org/add-fonts-fedora/

作者:Paul W. Frields 译者:geekpi 校对:wxy

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

在本 WSL 教程中了解如何执行像挂载 USB 驱动器和操作文件等任务。

 title=

之前的教程中,我们学习了如何在 Windows 10 上设置 WSL。你可以在 Windows 10 中使用 WSL 执行许多 Linux 命令。无论是基于 Linux 的系统还是 macOS,它们的许多系统管理任务都是在终端内部完成的。然而,Windows 10 缺乏这样的功能。你想运行一个 cron 任务么?不行。你想 SSH 进入你的服务器,然后 rsync 文件么?没门。如何用强大的命令行工具管理本地文件,而不是使用缓慢和不可靠的 GUI 工具呢?

在本教程中,你将看到如何使用 WSL 执行除了管理之外的任务 —— 例如挂载 USB 驱动器和操作文件。你需要运行一个完全更新的 Windows 10 并选择一个 Linux 发行版。我在上一篇文章中介绍了这些步骤,所以如果你跟上进度,那就从那里开始。让我们开始吧。

保持你的 Linux 系统更新

事实上,当你通过 WSL 运行 Ubuntu 或 openSUSE 时,其底层并没有运行 Linux 内核。然而,你必须保持你的发行版完整更新,以保护你的系统免受任何新的已知漏洞的影响。由于在 Windows 应用商店中只有两个免费的社区发行版,所以教程将只覆盖以下两个:openSUSE 和 Ubuntu。

更新你的 Ubuntu 系统:

# sudo apt-get update
# sudo apt-get dist-upgrade

运行 openSUSE 的更新:

# zypper up

您还可以使用 dup 命令将 openSUSE 升级到最新版本。但在运行系统升级之前,请使用上一个命令运行更新。

# zypper dup

注意: openSUSE 默认为 root 用户。如果你想执行任何非管理员任务,请切换到非特权用户。您可以这篇文章中了解如何在 openSUSE上 创建用户。

管理本地文件

如果你想使用优秀的 Linux 命令行工具来管理本地文件,你可以使用 WSL 轻松完成此操作。不幸的是,WSL 还不支持像 lsblkmount 这样的东西来挂载本地驱动器。但是,你可以 cd 到 C 盘并管理文件:

/mnt/c/Users/swapnil/Music

我现在在 C 盘的 Music 目录下。

要安装其他驱动器、分区和外部 USB 驱动器,你需要创建一个挂载点,然后挂载该驱动器。

打开文件资源管理器并检查该驱动器的挂载点。假设它在 Windows 中被挂载为 S:\。

在 Ubuntu/openSUSE 终端中,为驱动器创建一个挂载点。

sudo mkdir /mnt/s

现在挂载驱动器:

mount -f drvfs S: /mnt/s

挂载完毕后,你现在可以从发行版访问该驱动器。请记住,使用 WSL 方式运行的发行版将会看到 Windows 能看到的内容。因此,你无法挂载在 Windows 上无法原生挂载的 ext4 驱动器。

现在你可以在这里使用所有这些神奇的 Linux 命令。想要将文件从一个文件夹复制或移动到另一个文件夹?只需运行 cpmv 命令。

cp /source-folder/source-file.txt /destination-folder/
cp /music/classical/Beethoven/symphony-2.mp3 /plex-media/music/classical/

如果你想移动文件夹或大文件,我会推荐 rsync 而不是 cp 命令:

rsync -avzP /music/classical/Beethoven/symphonies/ /plex-media/music/classical/

耶!

想要在 Windows 驱动器中创建新目录,只需使用 mkdir 命令。

想要在某个时间设置一个 cron 作业来自动执行任务吗?继续使用 crontab -e 创建一个 cron 作业。十分简单。

你还可以在 Linux 中挂载网络/远程文件夹,以便你可以使用更好的工具管理它们。我的所有驱动器都插在树莓派或者服务器上,因此我只需 ssh 进入该机器并管理硬盘。在本地计算机和远程系统之间传输文件可以再次使用 rsync 命令完成。

WSL 现在已经不再是测试版了,它将继续获得更多新功能。我很兴奋的两个特性是 lsblk 命令和 dd 命令,它们允许我在 Windows 中本机管理我的驱动器并创建可引导的 Linux 驱动器。如果你是 Linux 命令行的新手,前一篇教程将帮助你开始使用一些最基本的命令。


via: https://www.linux.com/blog/learn/2018/2/how-use-wsl-linux-pro

作者:SWAPNIL BHARTIYA 译者:geekpi 校对:wxy

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

刚接触 Linux?在这篇教程中将学习如何轻松地在命令行列出、移动和编辑文件。

这是关于迁徙到 Linux 系列的第四篇文章了。如果您错过了之前的内容,可以回顾我们之前谈到的内容 新手之 Linux文件和文件系统、和 图形环境。Linux 无处不在,它可以用于运行大部分的网络服务器,如 Web、email 和其他服务器;它同样可以在您的手机、汽车控制台和其他很多设备上使用。现在,您可能会开始好奇 Linux 系统,并对学习 Linux 的工作原理萌发兴趣。

在 Linux 下,命令行非常实用。Linux 的桌面系统中,尽管命令行只是可选操作,但是您依旧能看见很多朋友开着一个命令行窗口和其他应用窗口并肩作战。在互联网服务器上和在设备中运行 Linux 时(LCTT 译注:指 IoT),命令行通常是唯一能直接与操作系统交互的工具。因此,命令行是有必要了解的,至少应当涉猎一些基础命令。

在命令行(通常称之为 Linux shell)中,所有操作都是通过键入命令完成。您可以执行查看文件列表、移动文件位置、显示文件内容、编辑文件内容等一系列操作,通过命令行,您甚至可以查看网页中的内容。

如果您在 Windows(CMD 或者 PowerShell) 上已经熟悉关于命令行的使用,您是否想跳转到“Windows 命令行用户”的章节上去?先阅读这些内容吧。

导航

在命令行中,这里有一个当前工作目录(文件夹和目录是同义词,在 Linux 中它们通常都被称为目录)的概念。如果没有特别指定目录,许多命令的执行会在当前目录下生效。比如,键入 ls 列出文件目录,当前工作目录的文件将会被列举出来。看一个例子:

$ ls
Desktop Documents Downloads Music Pictures README.txt Videos

ls Documents 这条命令将会列出 Documents 目录下的文件:

$ ls Documents
report.txt todo.txt EmailHowTo.pdf

通过 pwd 命令可以显示当前您的工作目录。比如:

$ pwd
/home/student

您可以通过 cd 命令改变当前目录并切换到您想要抵达的目录。比如:

$ pwd
/home/student
$ cd Downloads
$ pwd
/home/student/Downloads

路径中的目录由 /(左斜杠)字符分隔。路径中有一个隐含的层次关系,比如 /home/student 目录中,home 是顶层目录,而 studenthome 的子目录。

路径要么是绝对路径,要么是相对路径。绝对路径由一个 / 字符打头。

相对路径由 . 或者 .. 开始。在一个路径中,一个 . 意味着当前目录,.. 意味着当前目录的上级目录。比如,ls ../Documents 意味着在此寻找当前目录的上级名为 Documents 的目录:

$ pwd
/home/student
$ ls
Desktop Documents Downloads Music Pictures README.txt Videos
$ cd Downloads
$ pwd
/home/student/Downloads
$ ls ../Documents
report.txt todo.txt EmailHowTo.pdf

当您第一次打开命令行窗口时,您当前的工作目录被设置为您的家目录,通常为 /home/<您的登录名>。家目录专用于登录之后存储您的专属文件。

环境变量 $HOME 会展开为您的家目录,比如:

$ echo $HOME
/home/student

下表显示了用于目录导航和管理简单的文本文件的一些命令摘要。

搜索

有时我们会遗忘文件的位置,或者忘记了我要寻找的文件名。Linux 命令行有几个命令可以帮助您搜索到文件。

第一个命令是 find。您可以使用 find 命令通过文件名或其他属性搜索文件和目录。举个例子,当您遗忘了 todo.txt 文件的位置,我们可以执行下面的代码:

$ find $HOME -name todo.txt
/home/student/Documents/todo.txt

find 程序有很多功能和选项。一个简单的例子:

find <要寻找的目录> -name <文件名>

如果这里有 todo.txt 文件且不止一个,它将向我们列出拥有这个名字的所有文件的所有所在位置。find 命令有很多便于搜索的选项比如类型(文件或是目录等等)、时间、大小和其他一些选项。更多内容您可以同通过 man find 获取关于如何使用 find 命令的帮助。

您还可以使用 grep 命令搜索文件的特定内容,比如:

grep "01/02/2018" todo.txt

这将为您展示 todo 文件中 01/02/2018 所在行。

获取帮助

Linux 有很多命令,这里,我们没有办法一一列举。授人以鱼不如授人以渔,所以下一步我们将向您介绍帮助命令。

apropos 命令可以帮助您查找需要使用的命令。也许您想要查找能够操作目录或是获得文件列表的所有命令,但是您不知道该运行哪个命令。您可以这样尝试:

apropos directory

要在帮助文档中,得到一个于 directiory 关键字的相关命令列表,您可以这样操作:

apropos "list open files"

这将提供一个 lsof 命令给您,帮助您列出打开文件的列表。

当您明确知道您要使用的命令,但是不确定应该使用什么选项完成预期工作,您可以使用 man 命令,它是 manual 的缩写。您可以这样使用:

man ls

您可以在自己的设备上尝试这个命令。它会提供给您关于使用这个命令的完整信息。

通常,很多命令都能够接受 help 选项(比如说,ls --help),列出命令使用的提示。man 页面的内容通常太繁琐,--help 选项可能更适合快速浏览。

脚本

Linux 命令行中最贴心的功能之一是能够运行脚本文件,并且能重复运行。Linux 命令可以存储在文本文件中,您可以在文件的开头写入 #!/bin/sh,后面的行是命令。之后,一旦文件被存储为可执行文件,您就可以像执行命令一样运行脚本文件,比如,

--- contents of get_todays_todos.sh ---
#!/bin/sh
todays_date=`date +"%m/%d/%y"`
grep $todays_date $HOME/todos.txt

脚本可以以一套可重复的步骤自动化执行特定命令。如果需要的话,脚本也可以很复杂,能够使用循环、判断语句等。限于篇幅,这里不细述,但是您可以在网上查询到相关信息。

Windows 命令行用户

如果您对 Windows CMD 或者 PowerShell 程序很熟悉,在命令行输入命令应该是轻车熟路的。然而,它们之间有很多差异,如果您没有理解它们之间的差异可能会为之困扰。

首先,在 Linux 下的 PATH 环境与 Windows 不同。在 Windows 中,当前目录被认为是该搜索路径(PATH)中的第一个文件夹,尽管该目录没有在环境变量中列出。而在 Linux 下,当前目录不会明确的放在搜索路径中。Linux 下设置环境变量会被认为是风险操作。在 Linux 的当前目录执行程序,您需要使用 ./(代表当前目录的相对目录表示方式) 前缀。这可能会搞糊涂很多 CMD 用户。比如:

./my_program

而不是

my_program

另外,在 Windows 环境变量的路径中是以 ;(分号) 分割的。在 Linux 中,由 : 分割环境变量。同样,在 Linux 中路径由 / 字符分隔,而在 Windows 目录中路径由 \ 字符分割。因此 Windows 中典型的环境变量会像这样:

PATH="C:\Program Files;C:\Program Files\Firefox;"

而在 Linux 中看起来像这样:

PATH="/usr/bin:/opt/mozilla/firefox"

还要注意,在 Linux 中环境变量由 $ 拓展,而在 Windows 中您需要使用百分号(就是这样: %PATH%)。

在 Linux 中,通过 - 使用命令选项,而在 Windows 中,使用选项要通过 / 字符。所以,在 Linux 中您应该:

a_prog -h

而不是

a_prog /h

在 Linux 下,文件拓展名并没有意义。例如,将 myscript 重命名为 myscript.bat 并不会因此而变得可执行,需要设置文件的执行权限。文件执行权限会在下次的内容中覆盖到。

在 Linux 中,如果文件或者目录名以 . 字符开头,意味着它们是隐藏文件。比如,如果您申请编辑 .bashrc 文件,您不能在家目录中找到它,但是它可能真的存在,只不过它是隐藏文件。在命令行中,您可以通过 ls 命令的 -a 选项查看隐藏文件,比如:

ls -a

在 Linux 中,普通的命令与 Windows 的命令不尽相同。下面的表格显示了常用命令中 CMD 命令和 Linux 命令行的差异。


via: https://www.linux.com/blog/learn/2018/1/migrating-linux-command-line

作者:John Bonesio 译者:CYLeft 校对:wxy

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

持续集成 Continuous Integration (CI) 是为项目的每一项变更运行测试的过程,如同这是新的交付项目一样。如果持续执行,这意味着软件随时可以发布。 CI 是整个 IT 行业以及自由开源项目非常成熟的流程。Fedora 在这方面有点落后,但我们正在赶上。阅读以下内容了解进展。

我们为什么需要这个?

CI 将全面改善 Fedora。它通过尽早揭示 bug 提供更稳定和一致的操作系统。它让你在遇到问题时添加测试,以免再次发生(避免回归)。CI 可以运行来自上游的项目测试,还有测试集成在发行版中 Fedora 特定的测试。

最重要的是,一致的 CI 能自动化并减少手工劳动。它释放了我们宝贵的志愿者和贡献者,让他们将更多时间花在 Fedora 的新事物上。

它看起来如何?

对于初学者,我们将对在 Fedora 包仓库 (dist-git) 的每个提交运行测试。这些测试独立于构建时运行的每个软件包的测试。但是,它们在尽可能接近 Fedora 用户运行环境的环境中测试软件包的功能。除了特定的软件包测试外,Fedora 还运行一些发行版测试,例如从 F27 升级到 F28 或者全新安装。

软件包根据测试结果进行“控制”:测试失败会阻止将更新推送给用户。但是,有时由于各种原因,测试会失败。也许测试本身是错误的,或者不是最新的软件。或者可能发生基础架构问题,并阻止测试正常运行。维护人员能够重新触发测试或放弃测试结果,直到测试更新。

最终,当在 https://src.fedoraproject.org 上有合并请求或者更新时,Fedora 的 CI 将运行测试。这将使维护者了解建议的更改对包稳定性的影响,并帮助他们决定如何进行。

我们如今有什么?

目前,CI 管道在 Fedora Atomic Host 的部分软件包上运行测试。其他软件包可以在 dist-git 中进行测试,但它们不会自动运行。发行版特定的测试已经在我们所有的软件包上运行。这些测试结果被用于过滤测试失败的软件包。

我该如何参与?

最好的入门方法是阅读关于 Fedora 持续集成的文档。你应该熟悉标准测试接口,它描述了很多术语以及如何编写测试和使用现有的测试。

有了这些知识,如果你是一个软件包维护者,你可以开始添加测试到你的软件包。你可以在本地或虚拟机上运行它们。 (对于破坏性测试来说后者是明智的!)

标准测试接口使测试保持一致。因此,你可以轻松地将任何测试添加到你喜欢的包中,并在 [仓库]​​3 提交合并请求给维护人员。

在 irc.freenode.net 上与 #fedora-ci 联系,提供反馈,问题或关于 CI 的一般性讨论。


via: https://fedoramagazine.org/continuous-integration-fedora/

作者:Pierre-Yves Chibon 译者:geekpi 校对:wxy

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

这 13 个 Git 技巧将使你的版本控制技能 +1、+1、+1……

Git 是一个分布式版本控制系统,它已经成为开源世界中源代码控制的默认工具,在 4 月 7 日这天,它 13 岁了。使用 Git 令人沮丧的事情之一是你需要知道更多才能有效地使用 Git。但这也可能是使用 Git 比较美妙的一件事,因为没有什么比发现一个新技巧来简化或提高你的工作流的效率更令人快乐了。

为了纪念 Git 的 13 岁生日,这里有 13 条技巧和诀窍来让你的 Git 经验更加有用和强大。从你可能忽略的一些基本知识开始,并扩展到一些真正的高级用户技巧!

1、 你的 ~/.gitconfig 文件

当你第一次尝试使用 git 命令向仓库提交一个更改时,你可能会收到这样的欢迎信息:

*** Please tell me who you are.

Run

  git config --global user.email "[email protected]"

  git config --global user.name "Your Name"

to set your account's default identity.

你可能没有意识到正是这些命令在修改 ~/.gitconfig 的内容,这是 Git 存储全局配置选项的地方。你可以通过 ~/.gitconfig 文件来做大量的事,包括定义别名、永久性打开(或关闭)特定命令选项,以及修改 Git 工作方式(例如,git diff 使用哪个 diff 算法,或者默认使用什么类型的合并策略)。你甚至可以根据仓库的路径有条件地包含其他配置文件!所有细节请参阅 man git-config

2、 你仓库中的 .git/config 文件

在之前的技巧中,你可能想知道 git config 命令中 --global 标志是干什么的。它告诉 Git 更新 ~/.gitconfig 中的“全局”配置。当然,有全局配置也意味着会有本地配置,显然,如果你省略 --global 标志,git config 将改为更新仓库特有的配置,该配置存储在 .git/config 中。

.git/config 文件中设置的选项将覆盖 ~/.gitconfig 文件中的所有设置。因此,例如,如果你需要为特定仓库使用不同的电子邮件地址,则可以运行 git config user.email "[email protected]"。然后,该仓库中的任何提交都将使用你单独配置的电子邮件地址。如果你在开源项目中工作,而且希望它们显示自己的电子邮件地址,同时仍然使用自己工作邮箱作为主 Git 配置,这非常有用。

几乎任何你可以在 ~/.gitconfig 中设置的东西,你也可以在 .git/config 中进行设置,以使其作用于特定的仓库。在下面的技巧中,当我提到将某些内容添加到 ~/.gitconfig 时,只需记住你也可以在特定仓库的 .git/config 中添加来设置那个选项。

3、 别名

别名是你可以在 ~/.gitconfig 中做的另一件事。它的工作原理就像命令行中的 shell —— 它们设定一个新的命令名称,可以调用一个或多个其他命令,通常使用一组特定的选项或标志。它们对于那些你经常使用的又长又复杂的命令来说非常有效。

你可以使用 git config 命令来定义别名 —— 例如,运行 git config --global --add alias.st status 将使运行 git st 与运行 git status 做同样的事情 —— 但是我在定义别名时发现,直接编辑 ~/.gitconfig 文件通常更容易。

如果你选择使用这种方法,你会发现 ~/.gitconfig 文件是一个 INI 文件。INI 是一种带有特定段落的键值对文件格式。当添加一个别名时,你将改变 [alias] 段落。例如,定义上面相同的 git st 别名时,添加如下到文件:

[alias]
st = status

(如果已经有 [alias] 段落,只需将第二行添加到现有部分。)

4、 shell 命令中的别名

别名不仅仅限于运行其他 Git 子命令 —— 你还可以定义运行其他 shell 命令的别名。这是一个用来处理一个反复发生的、罕见和复杂的任务的很好方式:一旦你确定了如何完成它,就可以在别名下保存该命令。例如,我有一些 复刻 fork 的开源项目的仓库,并进行了一些本地修改。我想跟上项目正在进行的开发工作,并保存我本地的变化。为了实现这个目标,我需要定期将来自上游仓库的更改合并到我复刻的项目中 —— 我通过使用我称之为 upstream-merge 的别名来完成。它是这样定义的:

upstream-merge = !"git fetch origin -v && git fetch upstream -v && git merge upstream/master && git push"

别名定义开头的 ! 告诉 Git 通过 shell 运行这个命令。这个例子涉及到运行一些 git 命令,但是以这种方式定义的别名可以运行任何 shell 命令。

(注意,如果你想复制我的 upstream-merge 别名,你需要确保你有一个名为 upstream 的 Git 远程仓库,指向你已经分配的上游仓库,你可以通过运行 git remote add upstream <URL to repo> 来添加一个。)

5、 可视化提交图

如果你在一个有很多分支活动的项目上开发,有时可能很难掌握所有正在发生的工作以及它们之间的相关性。各种图形用户界面工具可让你获取不同分支的图片并在所谓的“提交图表”中提交。例如,以下是我使用 GitLab 提交图表查看器可视化的我的一个仓库的一部分:

 title=

如果你是一个专注于命令行的用户或者发现分支切换工具让人分心,那么可以从命令行获得类似的提交视图。这就是 git log 命令的 --graph 参数出现的地方:

 title=

以下命令可视化相同仓库可达到相同效果:

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative

--graph 选项将图添加到日志的左侧,--abbrev-commit 缩短提交的 SHA 值,--date=relative 以相对方式表示日期,以及 --pretty 来处理所有其他自定义格式。我有个 git lg 别名用于这个功能,它是我最常用的 10 个命令之一。

6、 更优雅的强制推送

有时,你越是想避开越避不开,你会发现你需要运行 git push --force 来覆盖仓库远程副本上的历史记录。你可能得到了一些反馈,需要你进行交互式 变基 rebase ,或者你可能已经搞砸了,并希望隐藏“罪证”。

当其他人在仓库的远程副本的同一分支上进行更改时,会发生强制推送的危险。当你强制推送已重写的历史记录时,这些提交将会丢失。这就是 git push --force-with-lease 出现的原因 -- 如果远程分支已经更新,它不会允许你强制推送,这确保你不会丢掉别人的工作。

7、 git add -N

你是否使用过 git commit -a 在一次行动中提交所有未完成的修改,但在你推送完提交后才发现 git commit -a 忽略了新添加的文件?你可以使用 git add -N (想想 “notify”) 来解决这个问题,告诉 Git 在第一次实际提交它们之前,你希望在提交中包含新增文件。

8、 git add -p

使用 Git 时的最佳做法是确保每次提交都只包含一个逻辑修改 —— 无论这是修复错误还是添加新功能。然而,有时当你在工作时,你的仓库中的修改最终应该使用多个提交。你怎样才能设法把事情分开,使每个提交只包含适当的修改呢?git add --patch 来拯救你了!

这个标志会让 git add 命令查看你工作副本中的所有变化,并为每个变化询问你是否想要将它提交、跳过,或者推迟决定(你可以在运行该命令后选择 ? 来查看其他更强大的选项)。git add -p 是生成结构良好的提交的绝佳工具。

9、 git checkout -p

git add -p 类似,git checkout 命令也接受 --patch-p 选项,这会使其在本地工作副本中显示每个“大块”的改动,并允许丢弃它 —— 简单来说就是将本地工作副本恢复到更改之前的状态。

这真的很棒。例如,当你追踪一个 bug 时引入了一堆调试日志语句,修正了这个 bug 之后,你可以先使用 git checkout -p 移除所有新的调试日志,然后 git add -p 来添加 bug 修复。没有比组合一个优雅的、结构良好的提交更令人满意!

10、 变基时执行命令

有些项目有一个规则,即存储库中的每个提交都必须处于可工作状态 —— 也就是说,在每次提交时,应该可以编译该代码,或者应该运行测试套件而不会失败。 当你在分支上工作时,这并不困难,但是如果你最终因为某种原因需要 变基 rebase 时,那么需要逐步完成每个变基的提交以确保你没有意外地引入一个中断,而这个过程是乏味的。

幸运的是,git rebase 已经覆盖了 -x--exec 选项。git rebase -x <cmd> 将在每个提交在变基中被应用后运行该命令。因此,举个例子,如果你有一个项目,其中使用 npm run tests 运行你的测试套件,git rebase -x npm run tests 将在变基期间每次提交之后运行测试套件。这使你可以查看测试套件是否在任何变基的提交中失败,以便你可以确认测试套件在每次提交时仍能通过。

11、 基于时间的修订引用

很多 Git 子命令都接受一个修订参数来决定命令作用于仓库的哪个部分,可以是某次特定的提交的 SHA1 值,一个分支的名称,甚至是一个符号性的名称如 HEAD(代表当前检出分支最后一次的提交),除了这些简单的形式以外,你还可以附加一个指定的日期或时间作为参数,表示“这个时间的引用”。

这个功能在某些时候会变得十分有用。当你处理最新出现的 bug,自言自语道:“这个功能昨天还是好好的,到底又改了些什么”,不用盯着满屏的 git log 的输出试图弄清楚什么时候更改了提交,你只需运行 git diff HEAD@{yesterday},看看从昨天以来的所有修改。这也适用于更长的时间段(例如 git diff HEAD@{'2 months ago'}),以及一个确切的日期(例如 git diff HEAD@{'2010-01-01 12:00:00'})。

你也可以将这些基于日期的修订参数与使用修订参数的任何 Git 子命令一起使用。在 gitrevisions 手册页中有关于具体使用哪种格式的详细信息。

12、 全知的 reflog

你是不是试过在变基时干掉过某次提交,然后发现你需要保留那个提交中一些东西?你可能觉得这些信息已经永远找不回来了,只能重新创建。但是如果你在本地工作副本中提交了,提交就会被添加到引用日志(reflog)中 ,你仍然可以访问到。

运行 git reflog 将在本地工作副本中显示当前分支的所有活动的列表,并为你提供每个提交的 SHA1 值。一旦发现你变基时放弃的那个提交,你可以运行 git checkout <SHA1> 跳转到该提交,复制任何你需要的信息,然后再运行 git checkout HEAD 返回到分支最近的提交去。

13、 自己清理

哎呦! 事实证明,我的基本数学技能不如我的 Git 技能。 Git 最初是在 2005 年发布的,这意味着它今年会变成 13 岁,而不是 12 岁(LCTT 译注:本文原来是以 12 岁生日为题的)。为了弥补这个错误,这里有可以让我们变成十三岁的第 13 条技巧。

如果你使用基于分支的工作流,随着在一个长期项目上的工作,除非你在每个分支合并时清理干净,否则你最终会得到一大堆分支。这使得你难于找到想要的分支,分支的森林会让你无从找起。甚至更糟糕的是,如果你有大量活跃的分支,确定一个分支是否被合并(可以被安全删除)或仍然没有被合并而应该留下会非常繁琐。幸运的是,Git 可以帮到你:只需要运行 git branch --merged 就可以得到已经被合并到你的当前分支的分支列表,或者 git branch --no-merged 找出被合并到其它分支的分支。默认情况下这会列出你本地工作副本的分支,但是如果你在命令行包括 --remote-r 参数,它也会列出仅存于远程仓库的已合并分支。

重要提示:如果你计划使用 git branch --merged 的输出来清理那些已合并的分支,你要小心它的输出也包括了当前分支(毕竟,这个当前的分支就被合并到当前分支!)。确保你在任何销毁动作之前排除了该分支(如果你忘记了,参见第 12 条技巧来学习 reflog 怎样帮你把分支找回来,希望有用……)。

以上是全部内容

希望这些技巧中至少有一个能够教给你一些关于 Git 的新东西,Git 是一个有 13 年历史的项目,并且在持续创新和增加新功能中。你最喜欢的 Git 技巧是什么?


via: https://opensource.com/article/18/4/git-tips

作者:John SJ Anderson 选题:lujun9972 译者:MjSeven 校对:wxy

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

在读这篇文章之前,确保你对 Python 全局、局部和非局部变量 有一定的基础。

global 关键字简介

在 Python 中,global 关键字允许你修改当前范围之外的变量。它用于创建全局变量并在本地上下文中更改变量。

global 关键字的规则

在 Python 中,有关 global 关键字基本规则如下:

  • 当我们在一个函数中创建一个变量时,默认情况下它是本地变量。
  • 当我们在一个函数之外定义一个变量时,默认情况下它是全局变量。你不必使用 global 关键字。
  • 我们使用 global 关键字在一个函数中来读写全局变量。
  • 在一个函数外使用 global 关键字没有效果。

使用 global 关键字(含示例)

我们来举个例子。

示例 1:从函数内部访问全局变量

c = 1 # 全局变量
def add():
    print(c)

add()

运行程序,输出为:

1

但是我们可能有一些场景需要从函数内部修改全局变量。

示例 2:在函数内部修改全局变量

c = 1 # 全局变量
def add():
    c = c + 2 # 将 c 增加 2
    print(c)
add()

运行程序,输出显示错误:

UnboundLocalError: local variable 'c' referenced before assignment

这是因为在函数中,我们只能访问全局变量但是不能修改它。

解决的办法是使用 global 关键字。

示例 3:使用 global 在函数中改变全局变量

c = 0 # global variable

def add():
    global c
    c = c + 2 # 将 c 增加 2
    print("Inside add():", c)

add()
print("In main:", c)

运行程序,输出为:

Inside add(): 2
In main: 2

在上面的程序中,我们在 add() 函数中定义了 c 将其作为全局关键字。

然后,我们给变量 c 增加 2,即 c = c + 2。之后,我们调用了 add() 函数。最后,打印全局变量 c

正如我们所看到的,在函数外的全局变量也发生了变化,c = 2

Python 模块中的全局变量

在 Python 中,我们创建一个单独的模块 config.py 来保存全局变量并在同一个程序中的 Python 模块之间共享信息。

以下是如何通过 Python 模块共享全局变量。

示例 4:在Python模块中共享全局变量

创建 config.py 文件来存储全局变量

a = 0
b = "empty"

创建 update.py 文件来改变全局变量

import config

config.a = 10
config.b = "alphabet"

创建 main.py 文件来测试其值的变化

import config
import update

print(config.a)
print(config.b)

运行 main.py,输出为:

10
alphabet

在上面,我们创建了三个文件: config.py, update.pymain.py

config.py 模块中保存了全局变量 ab。在 update.py 文件中,我们导入了 config.py 模块并改变了 ab 的值。同样,在 main.py 文件,我们导入了 config.pyupdate.py 模块。最后,我们打印并测试全局变量的值,无论它们是否被改变。

在嵌套函数中的全局变量

以下是如何在嵌套函数中使用全局变量。

示例 5:在嵌套函数中使用全局变量

def foo():
    x = 20
    def bar():
         global x
         x = 25

    print("Before calling bar: ", x)
    print("Calling bar now")
    bar()
    print("After calling bar: ", x)

foo()
print("x in main : ", x)

输出为:

Before calling bar: 20
Calling bar now
After calling bar: 20
x in main : 25

在上面的程序中,我们在一个嵌套函数 bar() 中声明了全局变量。在 foo() 函数中, 变量 x 没有全局关键字的作用。

调用 bar() 之前和之后, 变量 x 取本地变量的值,即 x = 20。在 foo() 函数之外,变量 x 会取在函数 bar() 中的值,即 x = 25。这是因为在 bar() 中,我们对 x 使用 global 关键字创建了一个全局变量(本地范围)。

如果我们在 bar() 函数内进行了任何修改,那么这些修改就会出现在本地范围之外,即 foo()


via: https://www.programiz.com/python-programming/global-keyword

作者:programiz 译者:MjSeven 校对:wxy

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