分类 软件开发 下的文章

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

 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中国 荣誉推出

了解 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中国 荣誉推出

通过编写“猜数字”游戏来学习 Elixir 编程语言,并将它与一个你熟知的语言做对比。

 title=

为了更好的学习一门新的编程语言,最好的方法是去关注主流语言的一些共有特征:

  • 变量
  • 表达式
  • 语句

这些概念是大多数编程语言的基础。因为这些相似性,只要你通晓了一门编程语言,你可以通过对比差异来熟知另一门编程语言。

另外一个学习新编程语言的好方法是开始编写一个简单标准的程序。它可以让你集中精力在语言上而非程序的逻辑本身。在这个系列的文章中,我们使用“猜数字”程序来实现,在这个程序中,计算机会选择一个介于 1 到 100 之间的数字,并要求你来猜测它。程序会循环执行,直到你正确猜出该数字为止。

“猜数字”这个程序使用了编程语言的以下概念:

  • 变量
  • 输入
  • 输出
  • 条件判断
  • 循环

这是一个学习新编程语言的绝佳实践。

猜数字的 Elixir 实现

Elixir 是一门被设计用于构建稳定可维护应用的动态类型的函数式编程语言。它与 Erlang 运行于同一虚拟机之上,吸纳了 Erlang 的众多长处的同时拥有更加简单的语法。

你可以编写一个 Elixir 版本的“猜数字”游戏来体验这门语言。

这是我的实现方法:

defmodule Guess do
  def guess() do
     random = Enum.random(1..100)
     IO.puts "Guess a number between 1 and 100"
     Guess.guess_loop(random)
  end
  def guess_loop(num) do
    data = IO.read(:stdio, :line)
    {guess, _rest} = Integer.parse(data)
    cond do
      guess < num ->
        IO.puts "Too low!"
        guess_loop(num)
      guess > num ->
        IO.puts "Too high!"
        guess_loop(num)
      true ->
        IO.puts "That's right!"
    end
  end
end

Guess.guess()

Elixir 通过列出变量的名称后面跟一个 = 号来为了给变量分配一个值。举个例子,表达式 random = 0random 变量分配一个数值 0。

代码以定义一个模块开始。在 Elixir 语言中,只有模块可以包含命名函数。

紧随其后的这行代码定义了入口函数 guess(),这个函数:

  • 调用 Enum.random() 函数来获取一个随机整数
  • 打印游戏提示
  • 调用循环执行的函数

剩余的游戏逻辑实现在 guess_loop() 函数中。

guess_loop() 函数利用 尾递归 来实现循环。Elixir 中有好几种实现循环的方法,尾递归是比较常用的一种方式。guess_loop() 函数做的最后一件事就是调用自身。

guess_loop() 函数的第一行读取用户输入。下一行调用 parse() 函数将输入转换成一个整数。

cond 表达式是 Elixir 版本的多重分支表达式。与其他语言中的 if/elif 或者 if/elsif 表达式不同,Elixir 对于的首个分支或者最后一个没有分支并没有区别对待。

这个 cond 表达式有三路分支:猜测的结果可以比随机数大、小或者相等。前两个选项先输出不等式的方向然后递归调用 guess_loop(),循环返回至函数开始。最后一个选项输出 That's right,然后这个函数就完成了。

输出例子

现在你已经编写了你的 Elixir 代码,你可以运行它来玩“猜数字”的游戏。每次你执行这个程序,Elixir 会选择一个不同的随机数,你可以一直猜下去直到你找到正确的答案:

$ elixir guess.exs
Guess a number between 1 and 100
50
Too high
30
Too high
20
Too high
10
Too low
15
Too high
13
Too low
14
That's right!

“猜数字”游戏是一个学习一门新编程语言的绝佳入门程序,因为它用了非常直接的方法实践了常用的几个编程概念。通过用不同语言实现这个简单的小游戏,你可以实践各个语言的核心概念并且比较它们的细节。

你是否有你最喜爱的编程语言?你将怎样用它来编写“猜数字”这个游戏?关注这个系列的文章来看看其他你可能感兴趣的语言实现。


via: https://opensource.com/article/20/12/elixir

作者:Moshe Zadka 选题:lujun9972 译者:tt67wq 校对:wxy

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

Hedy 是一种专门为教人编程而设计的新型编程语言。

 title=

学习编程既要学习编程逻辑,又要学习特定编程语言的语法。我在大学上第一堂编程课的时候,教的语言是 C++。第一个代码例子是基本的 “Hello World” 程序,就像下面的例子。

#include <iostream>

int main() {
    std::cout << "Hello World!";
    return 0;
}

老师直到几节课后才会解释大部分的代码。我们的期望是,我们只需输入代码,并最终了解为什么需要这些东西以及它们如何工作。

C++(以及其他类似的语言)的复杂语法是为什么 Python 经常被建议作为一种更容易的编程教学语言。下面是 Python 中的同一个例子:

print("Hello World!")

虽然 Python 中的 “Hello World” 基础例子要简单得多,但它仍然有复杂而精确的语法规则。print 函数需要在字符串周围加括号和引号。这对于没有编程经验的人来说,还是会感到困惑。Python 比 C++ 少了 “我以后再解释” 的语法问题,但还是有一些。

Hedy 是一种专门为编码教学而设计的新语言,它通过在语言中将复杂性分成多个关卡来解决语法复杂性的问题。Hedy 没有马上提供语言的全部功能,而是采取循序渐进的方式,随着学生在 Hedy 的学习的通关,慢慢变得更加复杂。随着关卡的进展,该语言获得了新的功能,最终变得更像 Python。目前有七个关卡,但更多的关卡正在计划中。

在第 1 关,Hedy 程序除了打印(print)一条语句(不需要引号或括号),提出(ask)一个问题,并回传(echo)一个答案外,不能做任何事情。第 1 关没有变量,没有循环,结构极精简。回传的工作原理几乎和变量一样,但只针对用户的最后一个输入。这可以让学生对基本概念感到舒适,而不必一下子学习所有的东西。

这是一个第 1 关的 Hedy “Hello World” 程序:

print Hello World

第 2 关引入了变量,但由于 print 函数没有使用引号,可能会出现一些有趣的结果。如果用来存储一个人的名字的变量是 name,那么就不可能打印输出 Your name is [name],因为 name 的第一次使用(本意是字符串)和第二次使用(是变量)都被解释为变量。如果将 name 设置为(isJohn Doe,那么 print Your name is name. 的输出就会是 Your John Doe is John Doe。虽然这听起来很奇怪,但这是一个引入变量概念的好方法,这恰好是第 3 关中增加的一个功能。

第 3 关要求在字符串周围加引号,这使得变量的功能就像在 Python 中一样。现在可以输出与变量相结合的字符串,做出复杂的语句,而不用担心变量名和字符串中的单词之间的冲突。这个级别取消了 “回传”(echo)函数,这看起来确实是一个可能会让一些学习者感到沮丧的东西。他们应该使用变量,这是更好的代码,但如果一个 ask/echo 代码块变成无效语法,可能会让人感到困惑。

第 4 关增加了基本的 if/else 功能。学生可以从简单的问/答代码转向复杂的交互。例如,一个问“你最喜欢的颜色是什么?”的提示可以根据用户输入的内容接受不同的回复。如果他们输入绿色,回答可以是“绿色!这也是我最喜欢的颜色。”如果他们输入其他的东西,回复可以是不同的。if/else 块是一个基本的编程概念,Hedy 引入了这个概念,而不必担心复杂的语法或过于精确的格式。

第 5 关有一个 repeat 函数,在现有的功能上增加了一个基本的循环。这个循环只能多次重复同一个命令,所以它没有 Python 中的循环那么强大,但它让学生习惯了重复命令的一般概念。这是多介绍了一个编程概念,而不会用无谓的复杂来拖累。学生们可以先掌握概念的基础知识,然后再继续学习同一事物的更强大、更复杂的版本。

在第 6 关,Hedy 现在可以进行基本的数学计算。加法、减法、乘法和除法都支持,但更高级的数学功能不支持。不能使用指数、模数或其他任何 Python 和其他语言能处理的东西。目前,Hedy 还没有更高关卡的产品增加更复杂的数学功能。

第 7 关引入了 Python 风格的缩进,这意味着 repeat 可以处理多行代码。学生在这之前都是逐行处理代码,但现在他们可以处理代码块。这个 Hedy 关卡与非教学型编程语言能做的事情相比还是有很大的差距,但它可以教会学生很多东西。

开始学习 Hedy 最简单的方法是访问 Hedy 网站上的 课程,目前有荷兰语、英语、法语、德语、葡萄牙语和西班牙语。这样一来,任何有网页浏览器的人都可以进入学习过程。也可以从 GitHub 下载 Hedy,并从命令行运行解释器,或者运行 Hedy 网站的本地副本及其交互式课程。基于网页的版本更容易使用,但网页版本和命令行版本都支持运行针对不同复杂程度的 Hedy 程序。

Hedy 永远不会与 Python、C++ 或其他语言竞争,成为现实世界项目编码的首选语言,但它是编码教学的绝佳方式。作为学习过程的一部分,学生编写的程序是真实的,甚至可能是复杂的。Hedy 可以促进学生的学习和创造力,而不会让学生在学习过程中过早地被过多的信息所迷惑。就像数学课一样,在进入微积分之前很久要从学习计数、相加等开始(这个过程需要数年时间),编程也不必一开始就对编程语言的语法问题“我稍后再解释”、精确地遵循这些语法问题,才能产生哪怕是最基本的语言程序。


via: https://opensource.com/article/21/4/hedy-teach-code

作者:Joshua Allen Holm 选题:lujun9972 译者:wxy 校对:wxy

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

Git 提供了几种方式可以帮你快速查看提交中哪些文件被改变。

 title=

如果你每天使用 Git,应该会提交不少改动。如果你每天和其他人在一个项目中使用 Git,假设 每个人 每天的提交都是安全的,你会意识到 Git 日志会变得多么混乱,似乎永恒地滚动着变化,却没有任何迹象表明修改了什么。

那么,你该怎样查看指定提交中文件发生哪些变化?这比你想的容易。

查看提交中文件发生的变化

要想知道指定提交中哪些文件发生变化,可以使用 git log --raw 命令。这是发现一个提交影响了哪些文件的最快速、最方便的方法。git log 命令一般都没有被充分利用,主要是因为它有太多的格式化选项,许多用户在面对很多选择以及在一些情况下不明所以的文档时,会望而却步。

然而,Git 的日志机制非常灵活,--raw 选项提供了当前分支中的提交日志,以及更改的文件列表。

以下是标准的 git log 输出:

$ git log
commit fbbbe083aed75b24f2c77b1825ecab10def0953c (HEAD -> dev, origin/dev)
Author: tux <[email protected]>
Date:   Sun Nov 5 21:40:37 2020 +1300

    exit immediately from failed download

commit 094f9948cd995acfc331a6965032ea0d38e01f03 (origin/master, master)
Author: Tux <[email protected]>
Date:   Fri Aug 5 02:05:19 2020 +1200

    export makeopts from etc/example.conf

commit 76b7b46dc53ec13316abb49cc7b37914215acd47
Author: Tux <[email protected]>
Date:   Sun Jul 31 21:45:24 2020 +1200

    fix typo in help message

即使作者在提交消息中指定了哪些文件发生变化,日志也相当简洁。

以下是 git log --raw 输出:

$ git log --raw
commit fbbbe083aed75b24f2c77b1825ecab10def0953c (HEAD -> dev, origin/dev)
Author: tux <[email protected]>
Date:   Sun Nov 5 21:40:37 2020 +1300

    exit immediately from failed download

:100755 100755 cbcf1f3 4cac92f M        src/example.lua

commit 094f9948cd995acfc331a6965032ea0d38e01f03 (origin/master, master)
Author: Tux <[email protected]>
Date:   Fri Aug 5 02:05:19 2020 +1200

    export makeopts from etc/example.conf
   
:100755 100755 4c815c0 cbcf1f3 M     src/example.lua
:100755 100755 71653e1 8f5d5a6 M     src/example.spec
:100644 100644 9d21a6f e33caba R100  etc/example.conf  etc/example.conf-default

commit 76b7b46dc53ec13316abb49cc7b37914215acd47
Author: Tux <[email protected]>
Date:   Sun Jul 31 21:45:24 2020 +1200

    fix typo in help message

:100755 100755 e253aaf 4c815c0 M        src/example.lua

这会准确告诉你哪个文件被添加到提交中,哪些文件发生改变(A 是添加,M 是修改,R 是重命名,D 是删除)。

Git whatchanged

git whatchanged 命令是一个遗留命令,它的前身是日志功能。文档说用户不应该用该命令替代 git log --raw,并且暗示它实质上已经被废弃了。不过,我还是觉得它是一个很有用的捷径,可以得到同样的输出结果(尽管合并提交的内容不包括在内),如果它被删除的话,我打算为它创建一个别名。如果你只想查看已更改的文件,不想在日志中看到合并提交,可以尝试 git whatchanged 作为简单的助记符。

查看变化

你不仅可以看到哪些文件发生更改,还可以使用 git log 显示文件中发生了哪些变化。你的 Git 日志可以生成一个内联差异,用 --patch 选项可以逐行显示每个文件的所有更改:

commit 62a2daf8411eccbec0af69e4736a0fcf0a469ab1 (HEAD -> master)
Author: Tux <[email protected]>
Date:   Wed Mar 10 06:46:58 2021 +1300

    commit

diff --git a/hello.txt b/hello.txt
index 65a56c3..36a0a7d 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,2 @@
 Hello
-world
+opensource.com

在这个例子中,“world” 这行字从 hello.txt 中删掉,“opensource.com” 这行字则添加进去。

如果你需要在其他地方手动进行相同的修改,这些 补丁 patch 可以与常见的 Unix 命令一起使用,例如 diff 与 patch。补丁也是一个好方法,可以总结指定提交中引入新信息的重要部分内容。当你在冲刺阶段引入一个 bug 时,你会发现这里的内容就是非常有价值的概述。为了更快地找到错误的原因,你可以忽略文件中没有更改的部分,只检查新代码。

用简单命令得到复杂的结果

你不必理解引用、分支和提交哈希,就可以查看提交中更改了哪些文件。你的 Git 日志旨在向你报告 Git 的活动,如果你想以特定方式格式化它或者提取特定的信息,通常需要费力地浏览许多文档来组合出正确的命令。幸运的是,关于 Git 历史记录最常用的请求之一只需要一两个选项:--raw--patch。如果你不记得 --raw,就想想“Git,什么改变了?”,然后输入 git whatchanged


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

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

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