第 1 章 Git 是什么
一次改动从本地到 Gitea 会经过四个区域,理解这四个区域即掌握 Git 的主要操作。
1.1 四个区域
工作区 暂存区 本地仓库 远程仓库
(编辑的文件) (待提交的) (提交历史) (Gitea)
│ │ │ │
│ git add │ git commit │ git push │
│ ─────────────> │ ─────────────> │ ─────────────> │
│ │ │ │
│ │ │ ◀──────────────│ git fetch
│ ◀──────────────│ │ │ git checkout / merge
取回(clone / pull)分两步:远程仓库 → 本地仓库 → 工作区,不会跳过本地仓库。
git clone:首次下载到本地仓库,再checkout到工作区。git pull:先fetch到本地仓库,再merge(或rebase)到工作区。git fetch只更新本地仓库,不碰工作区;想看新内容还需git merge或git checkout。- 工作区:硬盘上项目文件夹里、编辑器中可直接改的文件。
- 暂存区:一份"本次要提交哪些文件"的清单,用
git add加入。 - 本地仓库:
git commit把暂存区内容打包成一个提交,记入本地历史。仅在本机,他人看不到。 - 远程仓库:即 Gitea。
git push上传本地提交,git clone/git pull取回远程内容。
改文件 → git add(选文件)→ git commit(存本地)→ git push(传 Gitea)
1.2 add 与 commit 的区别
改了 a.py(已完成)和 b.py(未完成),只想提交 a.py:
git add a.py # 只把 a.py 加入暂存区
git commit -m "feat: 完成 a 功能" # 本次提交只含 a.py
b.py 的改动仍留在工作区,不受影响。逐个 add 需要的文件,不要用 git add .。
1.3 分支是可移动的指针
一个提交是项目某一时刻的完整快照,提交依次串成历史链。分支只是一个指向某个提交的、带名字的指针。
A ← B ← C ← D ← main
← feature/x (创建分支:新增一个同样指向 D 的指针)
在 feature/x 上提交后,该指针前移到新提交 E,main 不动:
A ← B ← C ← D ← main
\
E ← feature/x
创建分支几乎不耗时间、不占空间。未完成的改动挂在分支上,main 始终停在稳定状态。
1.4 冲突
两人改了同一文件的同一处,合并时 Git 暂停并标记冲突,交由人工决定。处理步骤见第 9 章。
1.5 五分钟实践
四个区域、add 与 commit 的区别、分支只是指针——这些看完即可理解。动手演练统一在 1.6 的 .quest-scratch 内进行(脚本可校验,且不会污染仓库)。
1.6 参考样例
体验四个区域与分支指针。演练在 .quest-scratch/git-demo 内(该目录被 .gitignore 忽略):
mkdir .quest-scratch\git-demo -Force
cd .quest-scratch\git-demo
git init
"hello" | Out-File -Encoding utf8 note.txt
git add note.txt
git commit -m "docs: 初始化 note"
git checkout -b test-branch
"world" | Add-Content note.txt
git add note.txt
git commit -m "docs: 追加一行"
git checkout main
Get-Content note.txt # 只有 hello
cd ..\..
若默认分支不是
main,运行git branch -M main统一。
自检:
python scripts/check-quest.py 1