一、思考题

Thinking 0.1 :Git的状态转换

思考下列有关 Git 的问题:

  • 在前述已初始化的 ~/learnGit 目录下,创建一个名为 README.txt 的文件。执 行命令 git status > Untracked.txt(其中的 > 为输出重定向,我们将在 0.6.3 中 详细介绍)。
  • README.txt 文件中添加任意文件内容,然后使用 add 命令,再执行命令 git status > Stage.txt
  • 提交 README.txt,并在提交说明里写入自己的学号。
  • 执行命令 cat Untracked.txtcat Stage.txt,对比两次运行的结果,体会 README.txt 两次所处位置的不同。
  • 修改 README.txt 文件,再执行命令 git status > Modified.txt
  • 执行命令 cat Modified.txt,观察其结果和第一次执行 add 命令之前的 status 是 否一样,并思考原因。

答:

  • 本思考题主要探讨的问题为Git中的四种状态转换关系,如下图

    image-20240311104956433
  • 第一次查看状态时重定向到Untracked.txt中的输出为:

    image-20240311104546116

    说明此时文件处于未追踪状态(Untracked)

  • 使用add命令后,第二次查看状态时的状态为:

    image-20240311104709625

    此时经过git add命令后,README.txtUntracked.txt被添加到暂存区(Staged)

  • 最后,提交并修改后再次查看状态:

    image-20240311110207393

    文件提交后处于Unmodified区,再对其进行修改后文件位于modified

  • 所以,对于思考题中的问题:观察其结果和第一次执行 add 命令之前的 status 是 否一样,并思考原因。

    答案是两次的status是不一样的,根据我上面的分析,第一次执行add命令之前的statusUntracked,而最后的statusmodified,所以状态不同

Thinking 0.2 :Git状态转换命令

仔细看看下图,思考一下箭头中的 add the file 、stage the file 和 commit 分别对应的是 Git 里的哪些命令呢?

image-20240311104956433
  • 还是上面思考题最前面放的那张图,本思考题要我们思考图中箭头对应的指令是什么
  • add the file:对应git add指令
  • stage the file :同样对应 git add 指令
  • commit: 对应 git commit 指令

Thinking 0.3 :Git文件恢复

思考下列问题:

  1. 代码文件 print.c 被错误删除时,应当使用什么命令将其恢复?
  2. 代码文件 print.c 被错误删除后,执行了 git rm print.c 命令,此时应当 使用什么命令将其恢复?
  3. 无关文件 hello.txt 已经被添加到暂存区时,如何在不删除此文件的前提下将其移出暂存区?

答:

  1. 执行 git checkout -- printf.c 指令,
  2. 先执行 git reset HEAD printf.c 指令,然后执行 git checkout -- printf.c 指令
  3. 执行 git rm --cached hello.txt 指令

Thinking 0.4:Git版本回退

思考下列有关 Git 的问题:

  • 找到在 /home/22xxxxxx/learnGit 下刚刚创建的 README.txt 文件,若不存 在则新建该文件。
  • 在文件里加入 Testing 1,git add,git commit,提交说明记为 1。 • 模仿上述做法,把 1 分别改为 2 和 3,再提交两次。
  • 使用 git log 命令查看提交日志,看是否已经有三次提交,记下提交说明为 3 的哈希值a。
  • 进行版本回退。执行命令 git reset --hard HEAD^ 后,再执行 git log,观 察其变化。
  • 找到提交说明为 1 的哈希值,执行命令 git reset --hard <hash> 后,再执行 git log,观察其变化。
  • 现在已经回到了旧版本,为了再次回到新版本,执行 git reset --hard <hash> ,再执行 git log,观察其变化。

答:

  • 按照题目中前三条操作后:

    image-20240311143945383

    我们可以发现已经有三次提交,提交3的哈希值a为13e87e5473698331de9e0c5e5b00c2ce222cc5e1

  • 执行 git reset --hard HEAD^进行版本回退后,再执行git log我们发现提交日志中只剩下两次提交,如下图:

    image-20240311144349852

    提交1的哈希值为e283774abeee6b0a5d4cb2a4d1174107938254be

  • 再执行git reset --hard e283774abeee6b0a5d4cb2a4d1174107938254be,版本再次回退,提交日志中只剩下提交1的日志

  • 执行完上述操作以及观察到对应现象后,我认为git reset 指令能让我们通过不同提交对应的哈希值,移动 HEAD 回退到任意的版本,更新暂存区和版本库的当前版本,从而实现版本回退。但在参数为 --hard 的情况下会同时覆盖掉工作目录下的文件,相当于把原本的工作目录使用回退版本库中的内容也全部覆盖掉;所以若工作目录下的文件还未提交,则 Git 仍会覆盖它从而导致无法恢复,有一定风险,所以也要慎用。

Thinking 0.5 :echo

执行如下命令, 并查看结果:

  • echo first
  • echo second > output.txt
  • echo third > output.txt
  • echo forth >> output.txt

答:

  • 执行完上面四条操作后,我们在终端看到了第一条命令执行输出的first,再查看output.txt中内容:

    image-20240311150737313
  • 我们发现只有thirdforth,并没有second。原因是第三条命令echo third > output.txt没有使用>>,所以将第二条命令在output.txt中的输出覆盖掉,而第四条使用了>>,将forth接在原来output.txt文件的末尾

Thinking 0.6 :

使用你知道的方法(包括重定向)创建下图内容的文件(文件命名为 test), 将创建该文件的命令序列保存在 command 文件中,并将 test 文件作为批处理文件运行,将 运行结果输出至 result 文件中。给出 command 文件和 result 文件的内容,并对最后的结 果进行解释说明(可以从 test 文件的内容入手). 具体实现的过程中思考下列问题:

  • echo echo Shell Start 与 echo echo Shell Start 效果是否有区别;
  • echo echo $c>file1 与 echo echo $c>file1 效果是否有区别.
image-20240314141116512

答:

  • command中内容:

    image-20240314143506189
  • result中内容:

    image-20240314143621967
  • 问题思考:

    1. echo echo Shell Start 与 echo echo Shell Start效果无区别,均为输出echo Shell Start
    2. echo echo $c>file1 与 echo echo \$c>file1效果有区别,在echo后面出现单引号时,会将单引号包裹的整体来输出

二、难点分析

gcc相关

之前我一直在使用各种ide一键即可编译运行.c文件,但在接触操作系统之后,对.c文件的预处理,编译,汇编,链接要靠命令行来完成,也是让刚入门的我感觉到很不习惯,下面列出一些gcc的常用命令,也方便我自己之后忘记时查看

  • gcc -E hello.c > 1.txt:只激活预处理,不生成文件(预处理一个最简单的输出hello world也会处理成几百行的代码)

  • gcc -S hello.c:进行预处理,汇编操作,生成汇编文件

  • gcc -c hello.c:生成hello.o文件,对文件进行了预处理,编译,汇编的工作

  • gcc -o hello hello.c gcc -o hello hello.o:进行预处理,编译,汇编,链接的工作,生成可执行文件hello,执行命令./hello即可执行

  • gcc -I ../include hello.c:如果hello.c中引用头文件,需要使用-I操作

bash脚本编写

bash脚本是lab0的一个重点,在课上以及课下实验中均出现了编写bash脚本的题目,大致的编写样例如下:

#!bin/bash
#首行用于保证直接执行我们的脚本时使用 bash 作为解释器,从第二行开始行首为#代表注释
#bash脚本内部其实就是linux命令行的顺序执行,基础命令在预习博客中,这里不介绍

#bash中传递参数
if [ $# -eq 0 ]
then
echo no parameter
elif [ $# -eq 1 ]
then
echo one parameter : $1
elif [$# -eq 2 ]
then
echo two parameters : $1 $2
else
echo many patameters : $*
fi
#上面代码中$#代表传递的参数个数,$*用一个字符串显示传递的全部参数

#while语句
n=1
while [ $n -le 10 ]
do
echo $n
let n=n+1
done

Makefile编写

在课下实验的第四题中,编写两个Makefile卡了我很长时间,最后看往年博客才彻底搞明白

Makefile的基本格式如下

target: dependencies
command 1
command 2
...
command n

其中:

  • target可以理解为指令名字,比如targetclean,那么执行make clean就是执行Makefileclean:的命令,如果只有make时,默认执行第一个target
  • dependeciestarget所依赖的文件或其他target
  • command就是要执行的命令,这里要注意,虽然这里可以写很多命令,但是每条命令都是独立的,比如我的命令需要完成:打开code文件夹并在code文件夹里面再make。那么我需要在一条命令中写cd code && make而不能拆成两条(这个点卡我好久)

Linux进阶操作

在lab0的课上课下实验中,也遇到了一些在os预习教程中没有见过的Linux操作,比如grep, sed, awk等文件处理操作,在刚刚使用时也是有不小的难度,具体使用细节可以在指导书中查看。

三、实验体会

总的来说,lab0的难度并不大,对我个人而言,难点在于对新工具的适应。比如,我觉得在bash脚本中对变量赋值本该是一件很简单的事,在课上extra中却一直毫无头绪;此外,对于awk等新操作的运用更是极其不熟练,只会一点最基本的操作,希望在之后的学习中可以慢慢用熟。

不过,对于刚刚接触操作系统,刚刚基础Linux命令的我来说,一切东西都是很新奇,实现很多新的操作也觉得很好玩,希望在之后的实验中也可以一直保持这样的心态,保持好奇,继续探索操作系统的世界。