SGBH6AXS / notesZhang Shuai's Personal Blog

Git 零基础入门:从第一次提交到协作

This post is only available in Chinese for now.

Git 零基础入门:从第一次提交到同学协作

课堂目标:能解释修改放在哪里,能独立提交一次修改,能通过分支和 Pull Request 与同学协作。

学习方式:先看演示,再自己操作,最后用自己的话解释结果。无需编程基础,今天只编辑 Markdown 文本。

01 · 课程安排与课前准备

时间 板块 你要完成的事
0–15 分钟 Git 为什么有用 区分 Git 与 GitHub,认识仓库
15–30 分钟 环境与练习项目 检查 Git,配置提交身份,建立仓库
30–65 分钟 工作区、暂存区、提交 做两次提交,解释两个 diff
65–85 分钟 分支与历史 建分支、切换、观察文件变化
85–95 分钟 休息 保留终端与编辑器
95–130 分钟 远程与 PR 推送分支,审核并合并一次 PR
130–155 分钟 冲突与撤销 复现冲突,人工解决,辨认撤销范围
155–175 分钟 独立任务 完成班级介绍贡献流程
175–180 分钟 回顾 回答检查题,使用速查表

课前由讲授者准备:Git、文本编辑器(如 VS Code)、平台账号;一个名为 git-classroom 的练习远程仓库,默认分支为 main,已有 README.md。提前邀请同学为协作者并检查推送权限。首次认证可能花时间,宜在课前完成。

课堂使用命令行帮助理解状态;Windows 推荐 Git Bash,macOS 可使用终端。下文的文件内容用编辑器填写并保存,命令在终端执行。包含 <...> 的命令是模板,运行前替换整个占位符,不能直接照抄。示例姓名是虚构的;练习不填写个人敏感信息。

讲授提示:每次输入命令之前,先问“你预计它会改变什么?”执行之后再用 git status 验证。

02 · Git 解决什么问题?

如果班级介绍文件叫“最终版”“最终版2”“最终版修复”,很难知道谁改过什么、哪次修改可以保留。Git 为项目保存版本历史,帮助比较变化、查找原因和整合多人修改。

名称 是什么 今天的用途
Git 在电脑上运行的分布式版本控制工具 记录提交、管理分支、合并修改
GitHub / GitLab / Gitea 托管 Git 仓库并提供协作的平台 共享提交、创建 PR、审核
Repository / Repo Git 管理的项目仓库 保存文件历史与相关信息
.git 通常位于项目根目录的 Git 元数据目录 交给 Git 管理,不手动编辑

Git 可以离线提交;远程同步需要能连接远程仓库。 常规 clone 会获得项目历史;浅克隆等特殊方式可能只下载部分历史。

Git 适合文本、代码和 Markdown;也能跟踪图片等二进制文件,但不能像文本那样逐行比较。它不替代所有备份方案。

课堂提问:断网时可以 commit 吗?同学是否能立即看到你的 commit?

可以在本地 commit。同学需通过远程同步或其他传递方式获取它;本地提交不会自动上传。

03 · 第一次配置与本地仓库

检查与配置


git --version

能看到版本号,表示 Git 可以调用。下文使用 switch 和 restore,需要 Git 2.23 或更新版本。


git config --global user.name "你的显示名称"

git config --global user.email "你的提交邮箱"

git config --global --get user.name

git config --global --get user.email

前两条中的内容要改为自己的信息。它们写入提交作者信息,不等于登录 GitHub。公开仓库的提交邮箱可能公开;可使用平台提供的隐私邮箱。--global 对当前系统用户生效;在单个仓库内不带它,可以设置该项目的身份。

本地练习:不依赖网络

在专门的练习目录执行,避免在其他项目内建立嵌套仓库:


mkdir git-local-practice

cd git-local-practice

git init -b main

用编辑器创建 README.md,填入并保存:


# 班级介绍

我们正在学习 Git。


git status

git add README.md

git diff --staged

git commit -m "Add classroom introduction"

git log --oneline

预期:新文件从 Untracked files 进入 Changes to be committed,commit 后工作区干净。这里没有远程仓库,也无需 push。

已有远程项目用 git clone <仓库地址>;新的本地项目用 git init。 clone 后一般不需要再 init。

04 · 核心:工作区、暂存区、本地与远程

位置 存放什么 哪个操作改变它
Working Tree 工作区 你当前看到和编辑的文件 编辑并保存文件
Staging Area 暂存区 下一次提交准备采用的文件内容 git add
Local Repository 本地仓库 已记录的提交历史 git commit
Remote Repository 远程仓库 对方仓库保存的提交与分支 git push 等同步操作

重点:保存文件不等于提交;暂存不等于提交;提交不等于上传。git add 记录执行当时的内容,不会持续跟随你的编辑。

演示一:修改 → 检查 → 暂存 → 提交

在 git-local-practice 中,把 README 的最后一句改为:


我们正在学习 Git,并练习团队协作。


git status

git diff

示意 diff(实际还会有文件路径和行号):


-我们正在学习 Git。

+我们正在学习 Git,并练习团队协作。

- 表示删除的行,+ 表示增加的行;一次替换通常表现为一删一增。然后执行:


git add README.md

git diff

git diff --staged

git commit -m "Describe classroom collaboration practice"

git status

为什么第二次 git diff 没有输出? 修改已暂存,工作区与暂存区一致;用 git diff --staged 才能看下一次提交会包含什么。没有输出不代表没有修改。

命令 比较对象 回答的问题
git diff 工作区与暂存区 还有哪些已跟踪文件的修改没暂存?
git diff --staged 暂存区与当前提交 下一次提交准备记录哪些变化?
git status 状态摘要 新文件、暂存、未暂存分别有哪些?

普通 git diff 不显示未跟踪新文件的内容。先在编辑器检查,暂存后再用 git diff --staged 检查。

演示二:暂存以后又编辑了

  1. README 新增一行 活动:周五读书会。,保存。

  2. 执行 git add README.md。

  3. 把这行改成 活动:周六读书会。,再次保存。

  4. 执行下面三条命令,先观察,不提交。


git status

git diff

git diff --staged

同一个文件可以同时出现于已暂存和未暂存修改中。

周五。暂存区仍是第二步记录的内容。要提交周六,需再次 git add README.md,检查 git diff --staged 后再 commit:


git add README.md

git diff --staged

git commit -m "Add Saturday reading activity"

提交信息与历史

提交记录项目快照,并带有作者、时间、父提交等信息。提交说明由人填写;Git 不会自动知道修改原因。提交哈希用于识别提交,通常可用足够长且无歧义的前缀。

模糊说明 更便于理解的说明
update Add Saturday reading activity
fix Fix spelling in classroom introduction
123 Add contribution instructions

中文提交说明也可以。一次提交尽量围绕一个目的,避免把无关修改放在一起。


git log --oneline

git log --oneline --graph --all

git show HEAD

若进入分页显示,按 q 退出。HEAD 在普通分支工作中指向当前分支,当前分支指向它的最新提交。

05 · 分支:把自己的修改单独推进

分支是指向提交的可移动引用,不是必须复制一份整个项目目录。创建分支后,在这个分支上的新提交不会自动加入 main。


git branch

git switch -c feature/activity

在 README 末尾加上并保存:


负责人:Alice。


git add README.md

git commit -m "Add reading activity coordinator"

git switch main

打开 README,负责人这一行应当消失。然后:


git switch feature/activity

这一行应当回来。切换分支会更新工作区文件,提交仍保存在历史中。

重点:未提交的修改不一定被分支隔离;它们可能跟着切换,也可能使切换被拒绝。课堂中先提交,再切换;遇到拒绝先看 git status。

本地合并演示


git switch main

git merge feature/activity

git log --oneline --graph --all

merge 把指定分支整合进当前分支。这里 main 没有额外提交,通常发生 fast-forward:main 直接前移,不创建新的合并提交。两边各有新提交时,正常 merge 可能创建含两个父提交的合并提交。

检查点:执行 git merge feature/activity 前,为什么要确认当前在 main?

因为合并更新的是当前分支。分支方向弄反,得到的结果就不符合目标。

06 · 远程仓库:clone、push、fetch、pull

从这里开始,切换到课堂远程项目。保留本地练习目录,进入它的父目录:


cd ..

git clone <课堂仓库的HTTPS地址>

cd git-classroom

git remote -v

git status

仓库地址从平台复制,项目文件夹名称以实际 clone 结果为准。HTTPS 与 SSH 都可用;本课采用课前配置好的认证方式。不要把访问令牌写进讲义或提交文件。

origin 是 clone 通常创建的远程名称,不是平台名,也不要求远程必须叫它。远程地址与操作权限是两件事:能 clone 不代表能 push。

命令 做什么 工作区会怎样
git push 发送本地提交并请求更新远程分支 不提交未提交文件
git fetch origin 获取远程对象与远程跟踪引用 不直接修改当前工作区
git pull --ff-only 获取远程更新,只允许快进整合 可快进则更新,否则拒绝

课堂统一使用显式 --ff-only,避免历史分叉时无意进行其他整合。普通 pull 的整合方式受参数与配置影响,不应简单理解为“覆盖本地”。


git switch main

git pull --ff-only origin main

git switch -c feature/alice-intro

创建 alice.md,填写:


# Alice

- 兴趣:摄影、阅读。

- 本次目标:学会通过 PR 提交修改。


git status

git add alice.md

git diff --staged

git commit -m "Add Alice introduction"

git push -u origin feature/alice-intro

-u 设置上游跟踪关系;以后在此分支通常可直接 git push。push 成功只表示远程有了这个分支,main 尚未因此合并。 每位同学使用不同文件名和分支名。

若无推送权限,请讲授者核对协作者权限。本课不引入 Fork;Fork 是平台层面的仓库复制,与本地 branch 不同。

07 · Pull Request:让同学看过再合并

PR 是平台提供的合并提议,不是 Git 命令;GitLab 常称 Merge Request。git pull 与 Pull Request 不是同一个操作。

创建与审核

在平台打开课堂仓库,进入创建 PR 的页面。不同平台按钮名称可能不同,重点核对:

字段 本例应选择
Base / Target(目标分支) main
Compare / Source(来源分支) feature/alice-intro
标题 Add Alice introduction
描述 做了什么、如何检查、需要同学关注什么

可以填写这样的描述:


新增 Alice 的介绍文件,包含兴趣与本次学习目标。

已预览 Markdown,并确认此次提交只包含 alice.md。

请检查文字是否清楚,以及是否需要补充介绍字段。

审核者先看 Files changed / Diff:有没有无关文件?有没有敏感信息?内容是否符合任务?如仓库有 CI,也应检查结果。CI 不替代人工审核。

处理一条审核意见

同学建议增加“想练习的命令”。在原分支修改 alice.md 并保存:


- 想练习的命令:git status、git diff。


git add alice.md

git diff --staged

git commit -m "Add commands to practice"

git push

同一来源分支的新提交会更新原 PR,无需再创建一个 PR。 审核通过后,由有权限的人在平台合并。本课无需展开不同合并策略。

合并后的本地同步


git switch main

git pull --ff-only origin main

检查 main 中是否出现 alice.md。平台上的合并不会自动更新你电脑中的 main。

讲授提示:请同学口述“本地 feature → 远程 feature → PR → 远程 main → 本地 main”的五个位置,检查是否把上传与合并混淆。

08 · 冲突:两个合理修改需要人来决定

冲突常见于双方修改同一段内容;同一文件的不同位置往往可以自动合并。删除与修改等情况也可能产生冲突。Git 能处理文本差异,但不能替团队决定最终含义。

可复现演示:回到本地练习目录

以下从 git-classroom 进入 git-local-practice,不推送,不影响课堂远程仓库。在开始前执行 git status,确保工作区干净。


cd ../git-local-practice

git switch main

用编辑器新建 meeting.txt,只写一行 时间待定,保存:


git add meeting.txt

git commit -m "Add meeting time placeholder"

git switch -c demo/alice

把该行改为 会议时间:周五 18:00,保存:


git add meeting.txt

git commit -m "Propose Friday meeting"

git switch main

git switch -c demo/bob

把同一行改为 会议时间:周六 10:00,保存:


git add meeting.txt

git commit -m "Propose Saturday meeting"

git merge demo/alice

git status

这里在 demo/bob 合并 demo/alice,会产生同一行的冲突。文件内容通常类似:


<<<<<<< HEAD

会议时间:周六 10:00

=======

会议时间:周五 18:00

>>>>>>> demo/alice

在这次普通 merge 中,HEAD 一侧来自当前 demo/bob,另一侧来自正在合并的 demo/alice。不要凭“Current / Incoming”字样盲选;先核对双方意图。

解决并完成

假设双方商定 会议时间:周六 14:00,用这行替换整个冲突块,删除所有冲突标记,保存:


git diff

git add meeting.txt

git diff --staged

git commit -m "Resolve meeting time conflict"

git status

git add 告诉 Git 该文件已解决;Git 不会替你验证约定是否正确。检查最终文本后再提交。

如果尚未解决、决定取消这次合并,可以在 merge 进行中执行:


git merge --abort

该命令不能在完成合并后当作撤销命令使用。合并前有未提交修改时,abort 不一定能完整恢复;因此演示从干净工作区开始。

09 · 撤销与忽略:先判断修改处在哪个阶段

三个情形,不要用同一条命令处理

情形 可用操作 影响
加入暂存区,但暂时不想提交 git restore --staged README.md 取消暂存,保留工作区内容;本课已有提交
已跟踪文件的未暂存修改确定不要 git restore README.md 用暂存区内容恢复工作区,丢弃该文件未暂存修改
已提交并共享,想撤销某次效果 下一阶段学习 git revert <提交ID> 新增反向提交,可能出现冲突

注意:git restore README.md 默认以暂存区为来源,不保证回到最近一次 commit。执行前先看两个 diff,确认要保留的内容。它不负责删除未跟踪新文件。

小练习:在本地练习仓库的新文件 scratch.md 写一句话,暂存,再用 git restore --staged scratch.md 取消暂存。确认文件仍在;不要与真实项目中的笔记混用。

本课不执行 reset --hard、clean -fd 或 push --force。前两者可能丢弃内容,强制推送可能改写共享分支历史。

.gitignore 示例

在项目根目录创建 .gitignore:


# 本机配置与凭据

.env

.env.*

!.env.example

# 依赖、构建产物与日志

node_modules/

dist/

*.log

这些是常见项目示例,不代表每个项目都必须采用同样规则。.env.example 应只放字段说明与虚构占位值。

.gitignore 主要作用于尚未跟踪的文件,不会让已跟踪文件自动停止跟踪。 若普通文件已经被跟踪,需要另行处理;若凭据已经进入历史,仅删除文件或增加忽略规则不够。先撤销或更换泄露凭据,再与维护者处理历史及副本。

提交 .gitignore 本身,让团队共享忽略规则。课堂可新建 practice.log,运行 git status,观察它不会作为新文件出现。

10 · 常见问题:先看状态,再找原因

提示或现象 常见原因 先做什么
not a git repository 终端不在项目目录 核对当前目录,进入 clone 的文件夹
Author identity unknown 提交身份未配置 检查 user.name 与 user.email
nothing to commit 无暂存修改,或编辑未保存 保存文件,检查 status 与两个 diff
新文件没有出现在 diff 文件尚未跟踪 在编辑器检查,add 后看 staged diff
no upstream branch 分支尚未设置上游 首次用 git push -u origin <分支名>
non-fast-forward / push rejected 远程分支已有本地缺少的提交等 status、fetch,核对历史;不要直接 force
pull --ff-only 拒绝 本地与远程不能快进整合 停下来与讲授者检查两边历史
切分支被拒绝 未提交修改可能被覆盖 看 status,先保存并处理修改
认证失败 / 权限不足 凭据、仓库地址或权限问题 核对地址、账号、协作者权限
平台没有显示最新内容 未 push、查看错分支等 核对当前分支、remote 与提交历史

求助时提供:正在做什么、刚执行的命令、完整报错、git status。隐藏令牌、密码和其他不应分享的信息。

11 · 独立实战:为班级介绍贡献一页

回到 git-classroom 目录。给自己 20 分钟,先隐藏参考流程:

  1. 检查状态,在干净工作区切到 main 并同步最新提交。

  2. 创建自己的分支,如 feature/bob-intro。

  3. 新建 bob.md,包括标题、兴趣、学习目标三部分。

  4. 检查文件内容,只暂存这次任务所需文件。

  5. 查看暂存差异,写清楚提交说明并 commit。

  6. 推送分支,创建目标为 main 的 PR。

  7. 与同学互相审查;根据意见修改一次并推送。

  8. 合并后更新本地 main,验证文件存在。

验收标准:提交包含正确文件;PR 方向正确;能解释 add / commit / push 的差别;能说明如何根据审核意见更新原 PR。

进入课堂项目后执行(使用自己尚未用过的分支名):


git status

git switch main

git pull --ff-only origin main

git switch -c feature/bob-intro

在编辑器创建并保存 bob.md,然后:


git status

git add bob.md

git diff --staged

git commit -m "Add Bob introduction"

git push -u origin feature/bob-intro

创建 PR、审核与合并在平台上完成。后续审核修改仍在原分支提交;合并后切回 main 再 pull。

12 · 五分钟复盘与命令速查

尝试用自己的话回答:

  1. Git 与 GitHub 各做什么?

  2. 为什么 add 后再编辑,需要重新 add?

  3. 为什么 commit 后同学还看不到修改?

  4. push 分支后,main 为什么没有变化?

  5. 同一个文件被两人修改,一定冲突吗?

  6. 如何取消暂存并保留修改?

  7. 为什么 .gitignore 不能删除已经提交的秘密?

  8. 不确定 Git 当前状态,先执行哪条命令?

  1. Git 管理版本;平台托管仓库与协作。

  2. add 记录当时的文件内容,后续编辑不会自动进入暂存区。

  3. commit 在本地,还需同步。

  4. 推送的是自己的分支,还需合并。

  5. 不一定,Git 常能自动合并互不重叠的修改。

  6. git restore --staged <文件>,本课仓库已有提交。

  7. 忽略规则不会清除过去的提交,也不自动停止跟踪已有文件。

  8. git status,随后视需要看两个 diff。

目的 命令
获取已有项目 git clone <地址>
看状态 git status
看未暂存差异 git diff
看待提交差异 git diff --staged
暂存指定文件 git add <文件>
取消暂存 git restore --staged <文件>
提交 git commit -m "说明"
看简洁历史 git log --oneline
创建并切换分支 git switch -c <新分支>
切换分支 git switch <已有分支>
看远程地址 git remote -v
首次推送当前分支 git push -u origin <分支>
后续推送 git push
获取远程信息 git fetch origin
在 main 上快进同步 git pull --ff-only origin main
合并进当前分支 git merge <来源分支>

日常顺序:检查状态 → 同步 main → 建分支 → 编辑 → 检查 diff → add → 检查 staged diff → commit → push → PR → review → merge → 更新本地 main。

今天最需要记住:知道修改现在在哪里,知道下一条命令会改变什么。遇到不明状态,先看 git status。

附录 · 讲授者的课前核对与下一阶段

  • 课前在自己的电脑走完远程认证、clone、推送和 PR 流程。

  • 两个练习目录用途不同:本地目录演示状态与冲突,远程目录练习协作。

  • 演示命令逐段执行,不要一次粘贴整页。每次 add 与 commit 之间都停下来检查。

  • 同学卡住时先让其解释 status,不直接代为输入所有命令。

  • 如果网络暂时不可用,先完成本地练习;远程协作部分须恢复连接后实操。

  • 下一阶段再学习 revert、stash、reflog、rebase、cherry-pick、标签与 CI;无需今天记住全部命令。

官方资料

Comments

No comments yet — be the first.

Comments are moderated. Plain text only.