初识Linux操作系统,了解bash、make以及git的基本指令
Thinking 0.1
- 在前述已初始化的~/learnGit 目录下,创建一个名为 README.txt 的文件。执行命令git status > Untracked.txt。
- 在README.txt 文件中添加任意文件内容,然后使用 add 命令,再执行命令 git status > Stage.txt。
- 提交README.txt,并在提交说明里写入自己的学号。
- 执行命令cat Untracked.txt 和 cat Stage.txt,对比两次运行的结果,体会README.txt 两次所处位置的不同。
- 修改README.txt 文件,再执行命令git status > Modified.txt。
- 执行命令cat Modified.txt,观察其结果和第一次执行 add 命令之前的 status 是否一样,并思考原因。
git@23373387:~/learnGit $ touch README.txt
git@23373387:~/learnGit $ git status > Untracked.txt
git@23373387:~/learnGit $ vim README.txt
git@23373387:~/learnGit $ git add README.txt
git@23373387:~/learnGit $ git status > Stage.txt
git@23373387:~/learnGit $ git commit -m "23373387"
[master (根提交) ca296b7] 23373387
1 file changed, 1 insertion(+)
create mode 100644 README.txt
git@23373387:~/learnGit (master)$ cat Untracked.txt
位于分支 master
尚无提交
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
README.txt
Untracked.txt
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
git@23373387:~/learnGit (master)$ cat Stage.txt
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: README.txt
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
Stage.txt
Untracked.txt
git@23373387:~/learnGit (master)$ vim README.txt
git@23373387:~/learnGit (master)$ git status > Modified.txt
git@23373387:~/learnGit (master)$ cat Modified.txt
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: README.txt
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
Modified.txt
Stage.txt
Untracked.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
- README.txt新建的时候,README.txt 处于未跟踪状态,Git 还没有对该文件进行版本管理。这是因为刚创建的文件,Git 不会自动将其纳入版本控制,需要使用 git add 命令将其添加到暂存区。
- 执行 git add README.txt 后,README.txt 被添加到了暂存区,处于待提交状态。暂存区是一个中间区域,用于准备要提交到版本库的文件。
- 当修改 README.txt 后,它处于已修改但未暂存的状态。这和第一次执行 add 命令之前的状态不同,第一次 README.txt 是未跟踪文件,而现在它已经是版本库中的文件,只是内容被修改了,需要再次使用 git add 命令将修改添加到暂存区,才能提交这些变更。
Thinking 0.2
仔细看看0.10,思考一下箭头中的add the file、stage the file和commit分别对应的是Git里的哪些命令呢?
- add the file、stage the file都指的是将文件添加到 Git 的暂存区这一操作,在 Git 里,对应的命令是 git add。
- commit 指的是将暂存区中的变更永久保存到本地仓库的历史记录中,在 Git 里,对应的命令是 git commit。
Thinking 0.3
- 代码文件print.c被错误删除时,应当使用什么命令将其恢复?
- 代码文件print.c被错误删除后,执行了git rm print.c命令,此时应当使用什么命令将其恢复?
- 无关文件hello.txt已经被添加到暂存区时,如何在不删除此文件的前提下将其移出暂存区
git checkout -- print.c
git reset HEAD print.c
git checkout -- print.c
git rm --cached hello.txt
Thinking 0.4
- 找到在/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,观察其变化。
git@23373387:~/learnGit (master)$ vim README.txt
git@23373387:~/learnGit (master)$ git add README.txt
git@23373387:~/learnGit (master)$ git commit -m "1"
[master e0eb896] 1
1 file changed, 1 insertion(+), 1 deletion(-)
git@23373387:~/learnGit (master)$ vim README.txt
git@23373387:~/learnGit (master)$ git add README.txt
git@23373387:~/learnGit (master)$ git commit -m "2"
[master 253ed28] 2
1 file changed, 1 insertion(+), 1 deletion(-)
git@23373387:~/learnGit (master)$ vim README.txt
git@23373387:~/learnGit (master)$ git add README.txt
git@23373387:~/learnGit (master)$ git commit -m "3"
[master 136dd66] 3
1 file changed, 1 insertion(+), 1 deletion(-)
git@23373387:~/learnGit (master)$ git log
commit 136dd6632f72eb168a6a9ce95d6d8f9f0e509137 (HEAD -> master)
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:57:25 2025 +0800
3
commit 253ed28d540ba3bc4af73129773e2316ba348202
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:56 2025 +0800
2
commit e0eb89678e8e64c235a12ae2aef580f39e1b914c
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:19 2025 +0800
1
git@23373387:~/learnGit (master)$ git reset --hard HEAD^
HEAD 现在位于 253ed28 2
git@23373387:~/learnGit (master)$ git log
commit 253ed28d540ba3bc4af73129773e2316ba348202 (HEAD -> master)
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:56 2025 +0800
2
commit e0eb89678e8e64c235a12ae2aef580f39e1b914c
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:19 2025 +0800
1
git@23373387:~/learnGit (master)$ git reset --hard e0eb89678e8e64c235a12ae2aef580f39e1b914c
HEAD 现在位于 e0eb896 1
git@23373387:~/learnGit (master)$ git log
commit e0eb89678e8e64c235a12ae2aef580f39e1b914c (HEAD -> master)
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:19 2025 +0800
1
git@23373387:~/learnGit (master)$ git reset --hard 136dd6632f72eb168a6a9ce95d6d8f9f0e509137
HEAD 现在位于 136dd66 3
git@23373387:~/learnGit (master)$ git log
commit 136dd6632f72eb168a6a9ce95d6d8f9f0e509137 (HEAD -> master)
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:57:25 2025 +0800
3
commit 253ed28d540ba3bc4af73129773e2316ba348202
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:56 2025 +0800
2
commit e0eb89678e8e64c235a12ae2aef580f39e1b914c
Author: 李昊霖 <23373387@buaa.edu.cn>
Date: Wed Mar 12 19:56:19 2025 +0800
1
- 执行 git reset –hard HEAD^ 命令会将当前分支的 HEAD 指针、暂存区和工作目录都重置到上一个提交版本。之后再执行 git log 时,最新的那次提交(即提交说明为 3 的那次提交)不再显示在日志中,日志中显示的最新提交变成了提交说明为 2 的那次提交。这是因为 git reset –hard 会直接丢弃指定版本之后的所有提交记录。
- 当执行 git reset –hard <提交说明为 1 的哈希值> 后,HEAD 指针、暂存区和工作目录会被重置到提交说明为 1 的那个版本。此时再执行 git log,日志中只会显示提交说明为 1 的这次提交以及它之前的提交,提交说明为 2 和 3 的提交记录都会被隐藏,
- 执行 git reset –hard <提交说明为 3 的哈希值> 后,HEAD 指针、暂存区和工作目录会被重置到提交说明为 3 的版本。再次执行 git log 时,日志会显示完整的三次提交记录,并且提交说明为 3 的提交会成为最新的提交记录,和最初三次提交完成后查看 git log 的结果是一样的。
Thinking 0.5
执行如下命令, 并查看结果
echo first
echo second > output.txt
echo third > output.txt
echo forth >> output.txt
git@23373387:~/learnGit (master)$ echo first
first
git@23373387:~/learnGit (master)$ echo second > output.txt
git@23373387:~/learnGit (master)$ cat output.txt
second
git@23373387:~/learnGit (master)$ echo third > output.txt
git@23373387:~/learnGit (master)$ cat output.txt
third
git@23373387:~/learnGit (master)$ echo forth >> output.txt
git@23373387:~/learnGit (master)$ cat output.txt
third
forth
- echo first 直接输出 first 到终端
- echo second > output.txt 将 second 写入 output.txt,覆盖原有内容,此时文件不存在,因此创建并写入。
- echo third > output.txt 再次将 third 写入 output.txt,覆盖之前的 second。
- echo forth » 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>file` 效果是否有区别。
command:
#!/bin/bash
echo "echo Shell Start..." >> test
echo "echo set a = 1" >> test
echo "a=1" >> test
echo "echo set b = 2" >> test
echo "b=2" >> test
echo "echo set c = a+b" >> test
echo "c=\$[\$a+\$b]" >> test
echo "echo c = \$c" >> test
echo "echo save c to ./file1" >> test
echo "echo \$c>file1" >> test
echo "echo save b to ./file2" >> test
echo "echo \$b>file2" >> test
echo "echo save a to ./file3" >> test
echo "echo \$a>file3" >> test
echo "echo save file1 file2 file3 to file4" >> test
echo "cat file1>file4" >> test
echo "cat file2>>file4" >> test
echo "cat file3>>file4" >> test
echo "echo save file4 to ./result" >> test
echo "cat file4>>result" >> test
result:
Shell Start...
set a = 1
set b = 2
set c = a+b
c = 3
save c to ./file1
save b to ./file2
save a to ./file3
save file1 file2 file3 to file4
save file4 to ./result
3
2
1
git@23373387:~/learnGit (master)$ vim command
git@23373387:~/learnGit (master)$ bash command
git@23373387:~/learnGit (master)$ bash test > result
git@23373387:~/learnGit (master)$ echo echo Shell Start
echo Shell Start
git@23373387:~/learnGit (master)$ echo `echo Shell Start`
Shell Start
git@23373387:~/learnGit (master)$ c=1
git@23373387:~/learnGit (master)$ echo echo $c>file1
git@23373387:~/learnGit (master)$ cat file1
echo 1
git@23373387:~/learnGit (master)$ echo `echo $c>file1`
git@23373387:~/learnGit (master)$ cat file1
1
- 脚本首先通过echo输出提示信息,然后定义变量a=1、b=2,通过 c=$[$a+$b] 计算 c 的值(a+b=3),接着通过重定向将 a、b、c 的值分别保存到 file1、file2、file3,再将这三个文件内容合并到 file4,最后将 file4 内容追加到 result。
- echo echo Shell Start 直接输出字符串 echo Shell Start,仅将内容作为普通文本展示,不执行任何命令解析,终端输出”echo Shell Start”。
- echo `echo Shell Start` 反引号会优先执行内部的echo Shell Start,得到结果 Shell Start,再通过外层echo在终端输出“Shell Start”。
- echo echo $c>file1 通过$c取出变量c的值,假设为1,而后将字符串“echo 1”写入 file1,由于命令的标准输出被重定向到文件,终端不输出内容。
- echo `echo $c>file1`有反引号先执行内部的 echo $c>file1,将变量c的值写入file1,由于反引号捕获的是命令的标准输出,但 echo $c>file1 的标准输出被重定向到文件,导致反引号捕获到空字符串,因此输出一个空行。
难点分析
-
跨目录 Makefile:直接在上级目录编写Makefile时,无法正确找到子目录中的头文件和源文件。为了解决这个问题,一方面,需要通过cd <path> && make 或 make -C <path> 调用子目录的Makefile,另一方面,需要在编译命令中使用 -I 参数指定头文件路径。
-
git 版本回退
-
git checkout -- <file>
:从版本库恢复文件到工作区。 -
git reset HEAD <file>
:撤销暂存区的修改。 -
git rm --cached <file>
:移除暂存区文件但保留工作区。
-
-
bash 易错点
- >和»的作用有区别,>用于覆盖写入,»用于追加写入。
- 小括号、中括号以及某些特殊符号的使用
符号 | 用途 | 示例 | 注意事项 |
---|---|---|---|
( ) | 命令组/数组初始化 | (cd dir; pwd) | 子shell不影响父环境 |
$( ) | 命令替换 | var=$(ls) | 推荐替代反引号 |
` ` | 命令替换(同 $()) | var=ls | 嵌套需转义 |
(( )) | 算术运算/条件判断 | ((a = 1 + 2)) | 变量可省略 $,运算符无空格 |
[ ] | 基本条件测试 | [ -f file ] | 空格严格,转义特殊字符 |
[[ ]] | 扩展条件测试(正则、逻辑运算) | [[ $str = file* ]] | 支持复杂表达式,无需转义通配符 |
-
文本处理(grep/sed/awk)
-
grep -E “ERROR WRONG” file:搜索包含指定模式的行。 -
sed ‘s/old/new/g’ file:替换文本中的字符串。
- awk -F: {print $1} file:把file中的每行文本用冒号分割,打印被分割的第一个字符串。
-
实验体会
-
通过实验,从Windows转向Linux环境,我适应了命令行界面的高效操作模式。在过程中,我掌握了常用命令和文件操作;理解了Git的分支和版本管理流程,能够完成代码协作与回滚;同时,掌握Makefile的编写规则,理解自动化编译的依赖关系管理;初步接触Shell脚本,学会通过脚本批量处理任务。
-
除此之外,我对C语言和汇编的理解相比大一更加深刻,面对编译错误或命令执行异常时,能通过错误信息和文档逐步排查,也能通过gdb等命令行调试工具对错误进行定位,还学会了充分利用官方手册和在线教程(如man命令)搜索解决自己的问题,提升了实践中的问题解决能力。