2020年6月

在 Linus Torvalds 建议之后内核淘汰 80 个字符长度限制

Linux 内核不再严格要求每行代码不超过 80 字符宽的编码风格。Linux 内核和很多历史比较长的开源项目一样,都有编码风格指南,要求每行代码不超过 80 字符(或 80 列)。Linux 作者 Linus Torvalds 上周在内核邮件列表上发表评论,反对一行代码在超过 80 字符后强行换行。而现在大多数人也不再使用 80x25(85 列 25 行)的终端了。当然开发者仍然可坚持每行最长 80 个字符,但是行长不再是硬限制。

来源:solidot

硬核老王点评:确实,还老抱着 80 个字符宽度限制太对不起这么大的显示器了。而且,事实上较长的单行编译代码搜索工具工作。

fastjson 被曝存在远程代码执行漏洞,等级“高危”

近日,阿里巴巴旗下的开源项目 fastjson( <= 1.2.68)被监测到存在新的反序列化远程代码执行漏洞。黑客利用该漏洞,可绕过 autoType 限制,直接远程执行任意命令攻击服务器,风险极大。 fastjson 官方建议升级到最新版本 1.2.69 或者更新的 1.2.70 版本。

来源:开源中国

硬核老王点评:fastjson 这种黑白名单的安全模式,总会遇到道高一尺魔高一丈的博弈情况。

Google Chrome 84 向滥用通知宣战

浏览器通知并不总是被用于其主要目的,最终成为推送恶意软件或获取用户隐私信息的工具。Google 称,“滥用通知提示是我们收到的关于 Chrome 浏览器的最多的用户投诉之一。很大比例的通知请求和通知来自于少数滥用网站”。Google 公司计划通过把滥用权限请求和滥用通知的网站列入“更安静的通知 UI”中来对抗滥用。当有网站试图欺骗用户点击特定的通知时,用户将被警告,从 2020 年 7 月 14 日上线的 Chrome 84 开始,用户将被警告。

来源:softpedia

硬核老王点评:本来通知这个功能出现是一种主动触及用户的好方式,但是被少数人滥用之后就非常讨厌了。不过,我倒是觉得,这种事情不用浏览器出手,遇到这种滥用通知的网站,就直接拉黑好了。

来试下这些开源工具。你的效率一定会提升。

 title=

诚然,很多人使用计算机来娱乐。但是一些人会用来工作,他们的理论是计算机应当能帮我们更快、更好、更有条理地做事。实际应用中,如果没有根据每个人的工作风格来做一些小小的手动配置,计算机也不会提升我们的效率。

Kevin Sonney 喜欢设计系统,今年他在一个 20 篇文章的系列中介绍了 18 种不同的生产力工具,不仅涵盖了网络方面,也涉及了一些能提升他的工作效率的工具。Kevin 最喜欢的所有的工具都收集到了本文,下面概括介绍每种工具的用途。

文件同步

重要的文件应谨慎管理。

  • Syncthing 能使不同设备上的文件彼此同步。设备可以是 Linux、Windows 或 Mac,也可以是服务器、Android 平板或手机,等等。文件可以是你期望在多台机器间同步的任意文件。Syncthing 是轻量级的点对点工具,因此你不需要支付服务费,你不需要第三方的服务器,而且它很快。
  • 同步是一件事,但有时你还需要帮忙处理你拥有的文件。假设你想要一个应用程序在作为一个图形化应用和作为控制台应用时表现不同行为,你可以通过修改符号链接指向的不同的配置文件来达成,如 .foo-gui.foo-term。这完全可以手动修改,但也可以用脚本处理,或者你可以试试 GNU Stow

邮件管理

我们都依赖于邮件和收件箱,但似乎很少有人对自己管理邮件的方式满意。如果你喜欢用终端工作,为什么不在终端里管理邮件呢?在终端里收发邮件是一件事,但是要能在终端里组织你的邮件就更棒了。如果你的职业是打字员或是天生写脚本的人,试试这类工具吧。

  • 我每天用 OfflineIMAP 把工作邮件同步到笔记本,以便用 Mutt 看邮件。它是很特别的工具,只做一件事:保证本地的邮件副本与远程的收件箱完全同步。配置和用 cron 调度它都相当简单,然后你就可以忘了它的存在。它相当简单,你与 IMAP 打交道的每一刻时间都应该用它。
  • Notmuch 能为邮件消息建立索引、加标签以及搜索邮件。如果你的收件箱出了问题,它可以让你不需要花费很大精力去补救。
  • Vim 可以收发邮件和管理你的日历。
  • 当然,Emacs 可以收发邮件和管理你的日历。

日历和联系人

我用过的所有的 Linux 系统都预装了 cal 命令。这是一个在终端下用的便捷小日历,它也是个很好的速查工具。然而,它几乎不能被称为一个日历应用程序。iCalendar 规范(与 Apple 的旧桌面日历无关)中提供了丰富的共享日历功能,虽然 .ics 的约会和事件是纯文本的,但没有在终端中管理它们的工作流。至少,在 khal 和 vdirsyncer 出现之前不存在。

  • Khal 是基于控制台的读写 .ics 文件的日历工具。
  • Vdirsyncer 是一个能把线上日历(和联系人)同步到本地的终端命令。Khal 在本地运行,vdirsyncer 在远程运行,这样远程的日历能与你管理的本地日历保持同步。
  • 管理联系人可能会很难,但是如果你用了 Khard 这个可以读写 vCard 格式文件的终端命令,就会变得简单。反过来,这些文件可以使用 vdirsyncer(你可能已经在使用 khal 日历)同步到远程服务器上。这使得日历和联系人管理变得简单,而且搭建个人信息管理(PIM)服务器也比以前容易得多。

待办清单

  • 组织你每天的行程有很多种方式,但是最简单的一种是用 todo.txt,一个简单、便携、易于理解的系统,即使设备上没有安装 todo.txt 也不会出现问题。todo.txt 能正常运行的原因是,它就是一个 Bash 脚本,能在几乎所有你能找到的的设备上运行。操作过程很简单:下载脚本,安装到家目录,用一个简单的命令开始调度任务。如果你的计算机上没有安装 todo.sh 命令,那么你的待办清单仍然可以作为纯文本文件来使用,你可以在需要时手动更新它。
  • Jrnl 是一个能追踪的你的日常议程和活动的数字笔记本。如果你要摘抄桌面上的报纸的片段或者把随意的想法写下来,那么这就是你要找的程序。

保持联络

沟通是关键,然而现在似乎比以往更多的是聊天平台的问题。这不仅仅是几个客户端,而是几个独立的网络。你怎么管理它们?这里有两个方案。

  • 如果你有很多的联系人分布在太多的聊天网络中,那么你应该试试 BitlBee,使用这个单一的聊天客户端就可以关联其他所有的聊天网络。
  • Rainbow Stream 是个推特客户端,能让你不被开放的网页浏览器分心,而又能紧跟时事。

消息通知

网页浏览器很好,但有时过犹不及。你希望能及时收到消息,但是你又不想全身心地陷入到互联网中。因为互联网是建立在开放的规范和大量的开源技术的基础上的,你不必在一个界面中做所有的事。对于不同的任务有不同的客户端,它们可以让你用自己喜欢的界面来获取你需要的信息。

  • Tuir 是一个 Reddit 终端客户端。
  • Newsboat 是一个 RSS 阅读器。
  • Wego 是天气预报工具。
  • Vim 可以帮助你登录 Reddit 和 Twitter。
  • Emacs 能让你保持与 Reddit、Twitter 和聊天客户端的联系。

保持终端一直开启

如果你正在用终端工作,那么关闭它的意义是什么呢?摆脱 exitCtrl+D 的诱惑,让你的控制台一直开启着。

  • Tmux 能分割你的终端,让一个终端窗口“分层"到另一个窗口之上,甚至从一台计算机离开到另一台计算机后,能保持相同的终端会话。
  • DESQview 是另一种方式:它本质上是一个终端窗口管理器。

未完待续

本文列出的工具只是 Linux 终端的神奇生产力工具中的一小部分。这个清单会结束,但你自己的清单可以继续。找到你喜欢的工具,学习它们,并将其发挥出最大的优势。当然,一个好的工具不一定要提高你的生产力:有时你最喜欢的命令也可以是能让你最快乐的命令。你的工作是找到自己喜欢的命令,用它们来改变世界。

玩得愉快!


via: https://opensource.com/article/20/6/productivity-tools-linux-terminal

作者:Alan Smithee 选题:lujun9972 译者:lxbwolf 校对:wxy

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

了解如何在 Drupal 中集成使用 WordPress 中流行的所见即所得编辑器。

 title=

自 2017 年以来,WordPress 的 Gutenberg 插件中的所见即所得编辑器就真的很不错。但是,Drupal 社区尚未就内容管理系统(CMS)编辑体验的最佳方法达成共识。但在社区的大量努力下,出现了一个强有力的新选择,将 Gutenberg 与 Drupal 集成在一起

以前,Drupal 8 中有两种主要的内容创建方法:

  • 基于段落的方法中,内容是由称为段落的实体组合而成。目前,大约有 100,000 个网站使用“段落”(Paragraphs)模块(根据 Drupal 说法)。
  • Layout-Builder 方法使用 Drupal 8.5 附带的编辑工具。它仍然在改进,但是它是下一个强有力的竞争者,因为它确实与 Drupal 内核很好地集成在一起。由于 Layout-Builder 是 Drupal 的一部分,因此无法获得使用情况的统计信息。

在 2018 年底,由 Fronkom(一家专注于开源解决方案的挪威数字机构)领导的 Drupal 社区将 WordPress Gutenberg 项目作为贡献模块移植到了 Drupal 中。让我们看一下 Gutenberg 在 Drupal 中的工作方式(包括一些很酷的 Drupal 特有的集成)。

安装

安装 Gutenberg 模块与安装任何 Drupal 模块一样简单,并且有良好的安装文档

配置

Gutenberg 已集成到 Drupal 的默认内容实体创建工作流中。你可以将其用于你选择的任何内容类型,前提是内容类型至少有一个文本区域字段,它是 Gutenberg 编辑器输出的位置。

要在 Drupal 中的内容类型启用 Gutenberg 项目,你必须进入设置:“结构 -> 内容类型”,并且,从要你想使用 Gutenberg 的内容类型旁边的下拉框中单击“编辑”。

 title=

在出现的窗口中,向下滚动并选择左侧的“Gutenberg 体验”选项卡,你可以在其中找到下面描述的设置。选择“启用 Gutenberg 体验”。

 title=

模板

这是 WordPress 开箱即用的很酷的功能之一。它能让你用 JSON 结构定义新页面模板。它将使用虚拟占位符内容预填充所有新创建的文章,这将有助于编辑者正确地构造内容。在上面的截图中,我添加了一个标题和一个段落。请注意,必须转义任何双引号。

模板锁

此设置允许你定义是否允许用户删除占位符内容,添加新块或仅编辑现有的预填充内容。

允许的 Gutenberg 和 Drupal 块

这是 Gutenberg Drupal 侧的另一个超酷功能。Drupal 允许用户创建各种类型的块来设计页面。例如,你可以创建一个块,其中包含五个最新博客的列表、最新评论或用于收集用户电子邮件的表单。

Gutenberg 与 Drupal 的深度集成允许用户在编辑时选择哪些 Drupal 块可供用户使用(例如,限制嵌入 YouTube),并将块用作内联内容。这是一个非常方便的功能,允许对用户体验进行精细控制。

在全新安装的 Drupal 中,没有太多的选择,但站点通常有许多提供各种功能的块。在下面的截图中,选择了“搜索表单”的 Drupal 块。

 title=

完成配置后,点击“保存内容类型”。

使用 Drupal Gutenberg 发布内容

启用 Gutenberg 内容类型后,它将接管大部分编辑体验。

 title=

在主窗口中,你可以看到我在上面的模板配置中添加的虚拟占位符内容。

特定于 Drupal 的选项

在右侧,Drupal 提供了一些字段和设置。例如,“标题” 字段是 Drupal 中所需的单独字段,因此它不在主页面上。

在“标题”下面,根据在 Drupal 中安装的模块和设置的选项,其他设置可能有所不同。你可以看到“修订日志消息”、“菜单设置”、“评论设置”以及添加“URL 别名”。

通常,Drupal 内容类型由多个文本字段组成,如标记、类别、复选框、图像字段等。当你启用 Gutenberg 内容类型时,这些附加字段可在“更多设置”选项卡中提供。

你现在可以添加内容 —— 它的工作方式与 WordPress Gutenberg 中的相同,并有额外的添加 Drupal 块的选项。

在下面的截图中,你可以看到当我添加一些文本替换占位符文本、来自 Drupal 的搜索块、标题、标记和自定义 URL 别名后发生的情况。

 title=

点击“保存”后,你的内容将发布。

 title=

就是这样,它工作良好。

共同工作以获得更好的软件体验

Drupal 中的 Gutenberg 工作良好。这是一个可供选择的方式,允许编辑者控制网站的外观,直至最细微的细节。它的采用率正在增长,截至本文撰写时,已有 1,000 多个安装,每月有 50 个新安装。Drupal 集成添加了其他很酷的功能,如细粒度权限、占位符内容,以及内联包含 Drupal 块的功能,这些功能在 WordPress 插件中没有。

很高兴看到两个独立项目的社区共同努力实现为人们提供更好的软件的共同目标。


via: https://opensource.com/article/20/3/gutenberg-editor-drupal

作者:MaciejLukianski 选题:lujun9972 译者:geekpi 校对:wxy

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

Dragon 飞船和 Falcon 9 火箭运行 Linux

SpaceX 的 Crew Dragon 飞船成功将 NASA 宇航员送入太空。Dragon 飞船和 Falcon 9 火箭都广泛使用定制版的 Linux 系统,飞行软件使用 C/C++ 编写,飞船内的图形显示应用是基于 Chromium/JS。飞船内的控制面板使用了令人耳目一新的触摸屏,宇航员的太空服也与传统太空服有明显差异,手套有触屏功能,有一根像“脐带” 似的缆线可以跟座椅连接,作为通讯和输送可呼吸空气的管道。

来源:solidot

硬核老王点评:关键性系统还是 Linux 更可靠。

B 站本月将发射哔哩哔哩视频卫星,国产自主研发

B 站计划今年 6 月下旬发射一颗名为“哔哩哔哩视频卫星”的遥感卫星,卫星所获的遥感视频、图片数据将用于 B 站科普。目前“哔哩哔哩视频卫星”官方账号已正式在 B 站上线,6 月下旬将对卫星发射全过程进行独家直播,今后还将在卫星拍摄的海量遥感视频、图片数据基础上定期更新科普视频,并为 B 站用户定制拍摄任务,用卫星航拍美丽地球。

来源:快科技

硬核老王点评:厉害了,后浪们!

Linux 5.7 发布:移除微软实现的 exFAT 文件系统加入三星的 exFAT

其它主要新特性包括:任务调度器支持热压,当 CPU 过热时热量调节器会限制 CPU 的最高频率,降低其最大可用计算能力;Split Lock 检测;频率一致性调度器;ARM 内核指针验证支持,防止指针遭修改减少安全漏洞;userfaultfd() 写保护支持;基于 BPF 的安全模块 bpf-lsm 等等。

来源:solidot

硬核老王点评:exFAT 也是个故事啊,只是不知道为啥换成了三星版本的。

IPv6 普及度突破 32%

根据 Google 统计,全球的 IPv6 普及度突破了 32%。按国别统计,中国只有 0.24%,美国 42%,加拿大 27.8%,俄罗斯 3.82%,印度 46%。因为移动网络、家庭宽带和企业网络在普及 IPv6 上的差异,当人们在工作时,统计数据会显示 IPv6 普及度出现下降,原因是移动网络和家庭宽带比企业网络更快普及 IPv6。

来源:solidot

硬核老王点评:中国的 IPv4 地址本来就不多,还不赶紧推动 IPv6?只要别推什么 IPv9 就行。

基于 Ubuntu 20.04 的 Linux Lite 5.0 正式发布

该项目团队表示:“这是迄今为止功能最丰富、最完整的 Linux Lite 版本。这是许多人期待已久的版本。现在开箱即支持 UEFI。GUFW 已经被高度可配置的 FireWallD 所取代。”

来源:cnBeta.COM

广泛应用于容器技术的 Linux 发行版 Alpine Linux 3.12.0 发布

这是 v3.12 稳定系列的首个版本。该发行版以安全为理念,面向 x86 路由器、防火墙、虚拟专用网、IP 电话盒及服务器而设计,广泛应用于 Docker 容器的底包。Alpine Linux 采用 musl libc 和 busybox 以减小系统的体积和运行时资源消耗。

来源:开源中国

硬核老王点评:Alpine 真正得到重视和流行,是其成为了很多 Docker 容器的底包,而随着容器技术的蓬勃发展而迅速流行。希望新的版本继续保持安全、精简的特色。

Git 核心的附加价值之一就是编辑历史记录的能力。与将历史记录视为神圣的记录的版本控制系统不同,在 Git 中,我们可以修改历史记录以适应我们的需要。这为我们提供了很多强大的工具,让我们可以像使用重构来维护良好的软件设计实践一样,编织良好的提交历史。这些工具对于新手甚至是有经验的 Git 用户来说可能会有些令人生畏,但本指南将帮助我们揭开强大的 git-rebase 的神秘面纱。

值得注意的是:一般建议不要修改公共分支、共享分支或稳定分支的历史记录。编辑特性分支和个人分支的历史记录是可以的,编辑还没有推送的提交也是可以的。在编辑完提交后,可以使用 git push -f 来强制推送你的修改到个人分支或特性分支。

尽管有这么可怕的警告,但值得一提的是,本指南中提到的一切都是非破坏性操作。实际上,在 Git 中永久丢失数据是相当困难的。本指南结尾介绍了在犯错误时进行纠正的方法。

设置沙盒

我们不想破坏你的任何实际的版本库,所以在整个指南中,我们将使用一个沙盒版本库。运行这些命令来开始工作。 1

git init /tmp/rebase-sandbox
cd /tmp/rebase-sandbox
git commit --allow-empty -m"Initial commit"

如果你遇到麻烦,只需运行 rm -rf /tmp/rebase-sandbox,并重新运行这些步骤即可重新开始。本指南的每一步都可以在新的沙箱上运行,所以没有必要重做每个任务。

修正最近的提交

让我们从简单的事情开始:修复你最近的提交。让我们向沙盒中添加一个文件,并犯个错误。

echo "Hello wrold!" >greeting.txt
git add greeting.txt
git commit -m"Add greeting.txt"

修复这个错误是非常容易的。我们只需要编辑文件,然后用 --amend 提交就可以了,就像这样:

echo "Hello world!" >greeting.txt
git commit -a --amend

指定 -a 会自动将所有 Git 已经知道的文件进行暂存(例如 Git 添加的),而 --amend 会将更改的内容压扁到最近的提交中。保存并退出你的编辑器(如果需要,你现在可以修改提交信息)。你可以通过运行 git show 看到修复的提交。

commit f5f19fbf6d35b2db37dcac3a55289ff9602e4d00 (HEAD -> master)
Author: Drew DeVault 
Date:   Sun Apr 28 11:09:47 2019 -0400

    Add greeting.txt

diff --git a/greeting.txt b/greeting.txt
new file mode 100644
index 0000000..cd08755
--- /dev/null
+++ b/greeting.txt
@@ -0,0 +1 @@
+Hello world!

修复较旧的提交

--amend 仅适用于最近的提交。如果你需要修正一个较旧的提交会怎么样?让我们从相应地设置沙盒开始:

echo "Hello!" >greeting.txt
git add greeting.txt
git commit -m"Add greeting.txt"

echo "Goodbye world!" >farewell.txt
git add farewell.txt
git commit -m"Add farewell.txt"

看起来 greeting.txt 像是丢失了 "world"。让我们正常地写个提交来解决这个问题:

echo "Hello world!" >greeting.txt
git commit -a -m"fixup greeting.txt"

现在文件看起来正确,但是我们的历史记录可以更好一点 —— 让我们使用新的提交来“修复”(fixup)最后一个提交。为此,我们需要引入一个新工具:交互式变基。我们将以这种方式编辑最后三个提交,因此我们将运行 git rebase -i HEAD~3-i 代表交互式)。这样会打开文本编辑器,如下所示:

pick 8d3fc77 Add greeting.txt
pick 2a73a77 Add farewell.txt
pick 0b9d0bb fixup greeting.txt

# Rebase f5f19fb..0b9d0bb onto f5f19fb (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# f, fixup <commit> = like "squash", but discard this commit's log message

这是变基计划,通过编辑此文件,你可以指导 Git 如何编辑历史记录。我已经将该摘要削减为仅与变基计划这一部分相关的细节,但是你可以在文本编辑器中浏览完整的摘要。

当我们保存并关闭编辑器时,Git 将从其历史记录中删除所有这些提交,然后一次执行一行。默认情况下,它将选取(pick)每个提交,将其从堆中召唤出来并添加到分支中。如果我们对此文件根本没有做任何编辑,则将直接回到起点,按原样选取每个提交。现在,我们将使用我最喜欢的功能之一:修复(fixup)。编辑第三行,将操作从 pick 更改为 fixup,并将其立即移至我们要“修复”的提交之后:

pick 8d3fc77 Add greeting.txt
fixup 0b9d0bb fixup greeting.txt
pick 2a73a77 Add farewell.txt
技巧:我们也可以只用 f 来缩写它,以加快下次的速度。

保存并退出编辑器,Git 将运行这些命令。我们可以检查日志以验证结果:

$ git log -2 --oneline
fcff6ae (HEAD -> master) Add farewell.txt
a479e94 Add greeting.txt

将多个提交压扁为一个

在工作时,当你达到较小的里程碑或修复以前的提交中的错误时,你可能会发现写很多提交很有用。但是,在将你的工作合并到 master 分支之前,将这些提交“压扁”(squash)到一起以使历史记录更清晰可能很有用。为此,我们将使用“压扁”(squash)操作。让我们从编写一堆提交开始,如果要加快速度,只需复制并粘贴这些:

git checkout -b squash
for c in H e l l o , ' ' w o r l d; do
    echo "$c" >>squash.txt
    git add squash.txt
    git commit -m"Add '$c' to squash.txt"
done

要制作出一个写着 “Hello,world” 的文件,要做很多事情!让我们开始另一个交互式变基,将它们压扁在一起。请注意,我们首先签出了一个分支来进行尝试。因此,因为我们使用 git rebase -i master 进行的分支,我们可以快速变基所有提交。结果:

pick 1e85199 Add 'H' to squash.txt
pick fff6631 Add 'e' to squash.txt
pick b354c74 Add 'l' to squash.txt
pick 04aaf74 Add 'l' to squash.txt
pick 9b0f720 Add 'o' to squash.txt
pick 66b114d Add ',' to squash.txt
pick dc158cd Add ' ' to squash.txt
pick dfcf9d6 Add 'w' to squash.txt
pick 7a85f34 Add 'o' to squash.txt
pick c275c27 Add 'r' to squash.txt
pick a513fd1 Add 'l' to squash.txt
pick 6b608ae Add 'd' to squash.txt

# Rebase 1af1b46..6b608ae onto 1af1b46 (12 commands)
#
# Commands:
# p, pick <commit> = use commit
# s, squash <commit> = use commit, but meld into previous commit
技巧:你的本地 master 分支独立于远程 master 分支而发展,并且 Git 将远程分支存储为 origin/master。结合这种技巧,git rebase -i origin/master 通常是一种非常方便的方法,可以变基所有尚未合并到上游的提交!

我们将把所有这些更改压扁到第一个提交中。为此,将第一行除外的每个“选取”(pick)操作都更改为“压扁”(squash),如下所示:

pick 1e85199 Add 'H' to squash.txt
squash fff6631 Add 'e' to squash.txt
squash b354c74 Add 'l' to squash.txt
squash 04aaf74 Add 'l' to squash.txt
squash 9b0f720 Add 'o' to squash.txt
squash 66b114d Add ',' to squash.txt
squash dc158cd Add ' ' to squash.txt
squash dfcf9d6 Add 'w' to squash.txt
squash 7a85f34 Add 'o' to squash.txt
squash c275c27 Add 'r' to squash.txt
squash a513fd1 Add 'l' to squash.txt
squash 6b608ae Add 'd' to squash.txt

保存并关闭编辑器时,Git 会考虑片刻,然后再次打开编辑器以修改最终的提交消息。你会看到以下内容:

# This is a combination of 12 commits.
# This is the 1st commit message:

Add 'H' to squash.txt

# This is the commit message #2:

Add 'e' to squash.txt

# This is the commit message #3:

Add 'l' to squash.txt

# This is the commit message #4:

Add 'l' to squash.txt

# This is the commit message #5:

Add 'o' to squash.txt

# This is the commit message #6:

Add ',' to squash.txt

# This is the commit message #7:

Add ' ' to squash.txt

# This is the commit message #8:

Add 'w' to squash.txt

# This is the commit message #9:

Add 'o' to squash.txt

# This is the commit message #10:

Add 'r' to squash.txt

# This is the commit message #11:

Add 'l' to squash.txt

# This is the commit message #12:

Add 'd' to squash.txt

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Apr 28 14:21:56 2019 -0400
#
# interactive rebase in progress; onto 1af1b46
# Last commands done (12 commands done):
#    squash a513fd1 Add 'l' to squash.txt
#    squash 6b608ae Add 'd' to squash.txt
# No commands remaining.
# You are currently rebasing branch 'squash' on '1af1b46'.
#
# Changes to be committed:
#   new file:   squash.txt
#

默认情况下,这是所有要压扁的提交的消息的组合,但是像这样将其保留肯定不是你想要的。不过,旧的提交消息在编写新的提交消息时可能很有用,所以放在这里以供参考。

提示:你在上一节中了解的“修复”(fixup)命令也可以用于此目的,但它会丢弃压扁的提交的消息。

让我们删除所有内容,并用更好的提交消息替换它,如下所示:

Add squash.txt with contents "Hello, world"

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Apr 28 14:21:56 2019 -0400
#
# interactive rebase in progress; onto 1af1b46
# Last commands done (12 commands done):
#    squash a513fd1 Add 'l' to squash.txt
#    squash 6b608ae Add 'd' to squash.txt
# No commands remaining.
# You are currently rebasing branch 'squash' on '1af1b46'.
#
# Changes to be committed:
#   new file:   squash.txt
#

保存并退出编辑器,然后检查你的 Git 日志,成功!

commit c785f476c7dff76f21ce2cad7c51cf2af00a44b6 (HEAD -> squash)
Author: Drew DeVault
Date:   Sun Apr 28 14:21:56 2019 -0400

    Add squash.txt with contents "Hello, world"

在继续之前,让我们将所做的更改拉入 master 分支中,并摆脱掉这一草稿。我们可以像使用 git merge 一样使用 git rebase,但是它避免了创建合并提交:

git checkout master
git rebase squash
git branch -D squash

除非我们实际上正在合并无关的历史记录,否则我们通常希望避免使用 git merge。如果你有两个不同的分支,则 git merge 对于记录它们合并的时间非常有用。在正常工作过程中,变基通常更为合适。

将一个提交拆分为多个

有时会发生相反的问题:一个提交太大了。让我们来看一看拆分它们。这次,让我们写一些实际的代码。从一个简单的 C 程序 2 开始(你仍然可以将此代码段复制并粘贴到你的 shell 中以快速执行此操作):

cat <<EOF >main.c
int main(int argc, char *argv[]) {
    return 0;
}
EOF

首先提交它:

git add main.c
git commit -m"Add C program skeleton"

然后把这个程序扩展一些:

cat <<EOF >main.c
#include &ltstdio.h>

const char *get_name() {
    static char buf[128];
    scanf("%s", buf);
    return buf;
}

int main(int argc, char *argv[]) {
    printf("What's your name? ");
    const char *name = get_name();
    printf("Hello, %s!\n", name);
    return 0;
}
EOF

提交之后,我们就可以准备学习如何将其拆分:

git commit -a -m"Flesh out C program"

第一步是启动交互式变基。让我们用 git rebase -i HEAD~2 来变基这两个提交,给出的变基计划如下:

pick 237b246 Add C program skeleton
pick b3f188b Flesh out C program

# Rebase c785f47..b3f188b onto c785f47 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# e, edit <commit> = use commit, but stop for amending

将第二个提交的命令从 pick 更改为 edit,然后保存并关闭编辑器。Git 会考虑一秒钟,然后向你建议:

Stopped at b3f188b...  Flesh out C program
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

我们可以按照以下说明为提交添加新的更改,但我们可以通过运行 git reset HEAD^ 来进行“软重置” 3 。如果在此之后运行 git status,你将看到它取消了提交最新的提交,并将其更改添加到工作树中:

Last commands done (2 commands done):
   pick 237b246 Add C program skeleton
   edit b3f188b Flesh out C program
No commands remaining.
You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
  (Once your working directory is clean, run "git rebase --continue")

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

  modified:   main.c

no changes added to commit (use "git add" and/or "git commit -a")

为了对此进行拆分,我们将进行交互式提交。这使我们能够选择性地仅提交工作树中的特定更改。运行 git commit -p 开始此过程,你将看到以下提示:

diff --git a/main.c b/main.c
index b1d9c2c..3463610 100644
--- a/main.c
+++ b/main.c
@@ -1,3 +1,14 @@
+#include &ltstdio.h>
+
+const char *get_name() {
+    static char buf[128];
+    scanf("%s", buf);
+    return buf;
+}
+
 int main(int argc, char *argv[]) {
+    printf("What's your name? ");
+    const char *name = get_name();
+    printf("Hello, %s!\n", name);
     return 0;
 }
Stage this hunk [y,n,q,a,d,s,e,?]?

Git 仅向你提供了一个“大块”(即单个更改)以进行提交。不过,这太大了,让我们使用 s 命令将这个“大块”拆分成较小的部分。

Split into 2 hunks.
@@ -1 +1,9 @@
+#include <stdio.h>
+
+const char *get_name() {
+    static char buf[128];
+    scanf("%s", buf);
+    return buf;
+}
+
 int main(int argc, char *argv[]) {
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?
提示:如果你对其他选项感到好奇,请按 ? 汇总显示。

这个大块看起来更好:单一、独立的更改。让我们按 y 来回答问题(并暂存那个“大块”),然后按 q 以“退出”交互式会话并继续进行提交。会弹出编辑器,要求输入合适的提交消息。

Add get_name function to C program

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto c785f47
# Last commands done (2 commands done):
#    pick 237b246 Add C program skeleton
#    edit b3f188b Flesh out C program
# No commands remaining.
# You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
#
# Changes to be committed:
#   modified:   main.c
#
# Changes not staged for commit:
#   modified:   main.c
#

保存并关闭编辑器,然后我们进行第二次提交。我们可以执行另一次交互式提交,但是由于我们只想在此提交中包括其余更改,因此我们将执行以下操作:

git commit -a -m"Prompt user for their name"
git rebase --continue

最后一条命令告诉 Git 我们已经完成了此提交的编辑,并继续执行下一个变基命令。这样就行了!运行 git log 来查看你的劳动成果:

$ git log -3 --oneline
fe19cc3 (HEAD -> master) Prompt user for their name
659a489 Add get_name function to C program
237b246 Add C program skeleton

重新排序提交

这很简单。让我们从设置沙箱开始:

echo "Goodbye now!" >farewell.txt
git add farewell.txt
git commit -m"Add farewell.txt"

echo "Hello there!" >greeting.txt
git add greeting.txt
git commit -m"Add greeting.txt"

echo "How're you doing?" >inquiry.txt
git add inquiry.txt
git commit -m"Add inquiry.txt"

现在 git log 看起来应如下所示:

f03baa5 (HEAD -> master) Add inquiry.txt
a4cebf7 Add greeting.txt
90bb015 Add farewell.txt

显然,这都是乱序。让我们对过去的 3 个提交进行交互式变基来解决此问题。运行 git rebase -i HEAD~3,这个变基规划将出现:

pick 90bb015 Add farewell.txt
pick a4cebf7 Add greeting.txt
pick f03baa5 Add inquiry.txt

# Rebase fe19cc3..f03baa5 onto fe19cc3 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
#
# These lines can be re-ordered; they are executed from top to bottom.

现在,解决方法很简单:只需按照你希望提交出现的顺序重新排列这些行。应该看起来像这样:

pick a4cebf7 Add greeting.txt
pick f03baa5 Add inquiry.txt
pick 90bb015 Add farewell.txt

保存并关闭你的编辑器,而 Git 将为你完成其余工作。请注意,在实践中这样做可能会导致冲突,参看下面章节以获取解决冲突的帮助。

git pull –rebase

如果你一直在由上游更新的分支 <branch>(比如说原始远程)上做一些提交,通常 git pull 会创建一个合并提交。在这方面,git pull 的默认行为等同于:

git fetch origin <branch>
git merge origin/<branch>

假设本地分支 <branch> 配置为从原始远程跟踪 <branch> 分支,即:

$ git config branch.<branch>.remote
origin
$ git config branch.<branch>.merge
refs/heads/<branch>

还有另一种选择,它通常更有用,并且会让历史记录更清晰:git pull --rebase。与合并方式不同,这基本上 4 等效于以下内容:

git fetch origin
git rebase origin/<branch>

合并方式更简单易懂,但是如果你了解如何使用 git rebase,那么变基方式几乎可以做到你想要做的任何事情。如果愿意,可以将其设置为默认行为,如下所示:

git config --global pull.rebase true

当你执行此操作时,从技术上讲,你在应用我们在下一节中讨论的过程……因此,让我们也解释一下故意执行此操作的含义。

使用 git rebase 来变基

具有讽刺意味的是,我最少使用的 Git 变基功能是它以之命名的功能:变基分支。假设你有以下分支:

A--B--C--D--> master
   \--E--F--> feature-1
      \--G--> feature-2

事实证明,feature-2 不依赖于 feature-1 的任何更改,它依赖于提交 E,因此你可以将其作为基础脱离 master。因此,解决方法是:

git rebase --onto master feature-1 feature-2

非交互式变基对所有牵连的提交都执行默认操作(pick 5 ,它只是简单地将不在 feature-1 中的 feature-2 中提交重放到 master 上。你的历史记录现在看起来像这样:

A--B--C--D--> master
   |     \--G--> feature-2
   \--E--F--> feature-1

解决冲突

解决合并冲突的详细信息不在本指南的范围内,将来请你注意另一篇指南。假设你熟悉通常的解决冲突的方法,那么这里是专门适用于变基的部分。

有时,在进行变基时会遇到合并冲突,你可以像处理其他任何合并冲突一样处理该冲突。Git 将在受影响的文件中设置冲突标记,git status 将显示你需要解决的问题,并且你可以使用 git addgit rm 将文件标记为已解决。但是,在 git rebase 的上下文中,你应该注意两个选项。

首先是如何完成冲突解决。解决由于 git merge 引起的冲突时,与其使用 git commit 那样的命令,更适当的变基命令是 git rebase --continue。但是,还有一个可用的选项:git rebase --skip。 这将跳过你正在处理的提交,它不会包含在变基中。这在执行非交互性变基时最常见,这时 Git 不会意识到它从“其他”分支中提取的提交是与“我们”分支上冲突的提交的更新版本。

帮帮我! 我把它弄坏了!

毫无疑问,变基有时会很难。如果你犯了一个错误,并因此而丢失了所需的提交,那么可以使用 git reflog 来节省下一天的时间。运行此命令将向你显示更改一个引用(即分支和标记)的每个操作。每行显示你的旧引用所指向的内容,你可对你认为丢失的 Git 提交执行 git cherry-pickgit checkoutgit show 或任何其他操作。


  1. 我们添加了一个空的初始提交以简化本教程的其余部分,因为要对版本库的初始提交进行变基需要特殊的命令(即git rebase --root)。
  2. 如果要编译此程序,请运行 cc -o main main.c,然后运行 ./main 查看结果。
  3. 实际上,这是“混合重置”。“软重置”(使用 git reset --soft 完成)将暂存更改,因此你无需再次 git add 添加它们,并且可以一次性提交所有更改。这不是我们想要的。我们希望选择性地暂存部分更改,以拆分提交。
  4. 实际上,这取决于上游分支本身是否已变基或删除/压扁了某些提交。git pull --rebase 尝试通过在 git rebasegit merge-base 中使用 “ 复刻点 fork-point ” 机制来从这种情况中恢复,以避免变基非本地提交。
  5. 实际上,这取决于 Git 的版本。直到 2.26.0 版,默认的非交互行为以前与交互行为稍有不同,这种方式通常并不重要。

via: https://git-rebase.io/

作者:git-rebase 选题:lujun9972 译者:wxy 校对:wxy

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

链接 Link 是一种快捷访问机制,它通过一个文件指向原始文件或目录的方式实现快捷访问,同时还记录了原始文件或目录的一些信息。

链接允许多个不同文件对同一个文件进行引用。

什么是软链接

符号链接 Symbolic Link (symlink),又称 软链接 Soft Link ,是一种特殊的文件,它指向 Linux 系统上的另一个文件或目录。

这和 Windows 系统中的快捷方式有点类似,链接文件中记录的只是原始文件的路径,并不记录原始文件的内容。

符号链接通常用于对库文件进行链接,也常用于链接日志文件和 网络文件系统 Network File System (NFS)上共享的目录。

什么是硬链接

硬链接是原始文件的一个镜像副本。创建硬链接后,如果把原始文件删除,链接文件也不会受到影响,因为此时原始文件和链接文件互为镜像副本。

为什么要创建链接文件而不直接复制文件呢?

当你需要将同一个文件保存在多个不同位置,而且还要保持持续更新的时候,硬链接的重要性就体现出来了。

如果你只是单纯把文件复制到另一个位置,那么另一个位置的文件只会保存着复制那一刻的文件内容,后续也不会跟随着原始文件持续更新。

而使用硬链接时,各个镜像副本的文件内容都会同时更新。

软链接和硬链接的区别

下表列出了软链接和硬链接之间的区别。

#软链接硬链接
1软链接类似于 Windows 系统中的快捷方式硬链接是原始文件的一个镜像副本
2软链接又称符号链接硬链接没有别名
3链接中任何一个文件发生改变,都会同步到连接中的其它文件和软链接一样
4软链接可以跨文件系统进行创建硬链接不可以跨文件系统进行创建
5软链接可以指向文件或目录硬链接只能指向文件
6链接文件和原始文件之间的 inode 和文件权限不完全一致链接文件和原始文件的 inode 和文件权限完全一致
7链接文件只记录原始文件的路径,不记录原始文件的内容链接文件记录了原始文件的内容
8如果原始文件被移除,软链接就会因为指向不存在的文件而失效。这被称为“ 挂起链接 hanging link 即使原始文件被移除,链接文件也不受影响。
9通过 ln -s <原始文件> <链接文件> 命令创建软链接通过 ln <原始文件> <链接文件> 命令创建硬链接
10软链接文件的文件权限中有一个特殊标记 l硬链接文件没有特殊标记
11通过 find / -type l 命令可以查找软链接文件通过 find / -samefile <原始文件> 命令可以查找硬链接文件
12通过 symlinks <目录> 命令可以查找失效的软链接硬链接不存在失效链接

via: https://www.2daygeek.com/difference-between-soft-link-vs-hard-link-linux/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:HankChow 校对:wxy

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