1. 从零理解Git的版本阶段模型1.1 为什么每个学Python的人都绕不开Git刚开始学Python那会儿我最头疼的不是缩进报错也不是环境配置而是每次写完作业之后桌面上会出现一堆命名诡异的文件homework.py、homework_v2.py、homework_最终版.py、homework_最终版_真的最终版.py。交作业的时候自己都分不清哪个是哪个更别提老师收到一堆同名文件时的崩溃心情了。后来被逼着用上了Git才发现这东西解决的压根不是“备份”问题而是版本追溯和协作交付的问题。你可以把它想象成一个超级详细的“存档系统”每次你对代码做了一次有意义的修改就存一个档并且给这个档写一句备注。以后不管过了多久你都能翻回任何一个存档点看看当时改了什么、为什么改。对于交作业这个场景来说Git能让你清楚地记录“从拿到题目到最终提交”的完整过程老师如果愿意看提交记录甚至能看出你的解题思路是怎么一步步推进的。这篇文章主要面向两类人一类是刚开始学Python、第一次接触Git的学生另一类是想把自己写的小项目用Git管起来、但一直没搞明白“暂存区”“本地仓库”“远程仓库”到底怎么回事的自学者。我会从Git的几个核心阶段讲起把每个阶段到底在干什么、为什么要这么设计讲透然后手把手带你走一遍用Git提交作业的完整流程。中间会穿插我自己踩过的坑和一些能省时间的技巧尽量让你少走弯路。1.2 Git的四个核心阶段到底是什么很多人初学Git时最大的困惑就是我明明只是想把代码存起来为什么一会儿要add一会儿要commit一会儿又要push直接存不行吗要理解这个得先搞清楚Git把“保存代码”这件事拆成了四个阶段每个阶段对应一个不同的区域。工作区Working Directory就是你电脑上能直接看到、直接编辑的那个文件夹。你在里面新建、修改、删除文件这些操作首先发生在工作区。工作区里的文件状态是“活的”随时在变。暂存区Staging Area是一个中间过渡区域。你可以把它理解成“购物车”你在工作区里改了一堆文件但不是所有改动都想立刻存档于是你先挑出这次想存档的文件放进暂存区。git add这个命令干的就是“把文件放进购物车”这件事。为什么要多这一步因为实际开发中你经常同时改了好几个文件但只想把其中一部分作为一个完整的逻辑单元提交。比如你修了一个bug顺手还改了几行注释你希望这两件事分开记录暂存区就给了你这个选择权。本地仓库Local Repository是真正存放所有存档记录的地方。git commit会把暂存区里的内容打包成一个永久的快照存进本地仓库。每个快照都有一个唯一的编号commit hash并且记录了提交人、提交时间、提交说明以及指向上一个快照的指针。这一连串的快照就构成了版本历史。远程仓库Remote Repository是放在网络上的一个仓库副本常见的有各类代码托管平台提供的仓库服务。git push会把本地仓库里的快照上传到远程仓库git pull则把远程仓库的更新拉回本地。对于交作业来说远程仓库就是你和老师之间的“交付通道”。这四个阶段的关系可以用一句话概括工作区改文件暂存区挑改动本地仓库存快照远程仓库做交付。数据是单向流动的从工作区到暂存区到本地仓库再到远程仓库每一步都需要你明确地发出指令。Git不会自动帮你做任何事这既是它的门槛也是它的可控性所在。1.3 为什么交作业特别适合用Git有人可能会想我就交个Python作业用邮件附件发过去不就行了何必折腾Git这个想法在只交一次作业的时候确实成立但实际情况往往是老师可能要求你修改后重新提交或者作业本身分多个阶段完成又或者你需要和同学协作完成一个小组项目。这些场景下Git的优势就非常明显了。第一完整的修改记录。你什么时候开始做的、中间卡在哪里、怎么解决的提交历史里都有痕迹。有些老师甚至会根据提交频率和提交说明来判断你是不是最后一天才赶出来的。第二不怕改错。代码改崩了一条命令就能回退到之前任何一个正常的版本不用手动备份一堆文件。第三交付过程标准化。老师只需要给你一个远程仓库的地址你做完之后推送上去老师直接拉取查看不需要来回复制文件、确认版本。第四提前养成工程习惯。说实话学校里教的编程知识和工作里实际用的工程实践之间有很大一段距离而Git是这段距离里最容易补上、也最值得补上的一环。早一点把Git用熟以后参与任何稍微正规一点的开发工作都不会慌。2. 环境搭建与仓库初始化实操2.1 安装Git与最小化配置在开始用Git之前你得先确认电脑上有没有装。打开终端Windows用户用Git Bash或者PowerShellMac用户用Terminal输入git --version如果能看到版本号就说明已经装好了。如果没有去Git的官方网站下载对应系统的安装包一路默认选项安装即可。安装完成后还需要做一次最小化配置告诉Git你是谁。git config --global user.name 你的名字或昵称 git config --global user.email 你的邮箱这两条命令是必须的因为每次提交都会记录提交人信息。--global表示这是全局配置对这台电脑上的所有仓库生效。如果你在某个特定项目里想用不同的名字可以在那个项目目录下不加--global再配置一次局部配置会覆盖全局配置。还有一个配置我强烈建议加上它能让你在终端里看提交历史时更舒服git config --global core.quotepath false这个配置的作用是让Git在显示中文文件名时不要转义成八进制字符。不加的话你git status看到的中文文件名会是一串看不懂的编码非常影响体验。注意配置里的邮箱建议用你常用的邮箱因为远程仓库平台通常会根据邮箱来关联提交记录和账号。如果邮箱填错了你的提交在平台上可能不会显示在你的头像下面。2.2 创建本地仓库的两种方式配置好之后就可以创建仓库了。有两种常见场景一种是从零开始一个新项目另一种是把已有的文件夹变成Git仓库。从零开始的话先建一个文件夹进去之后执行mkdir python-homework cd python-homework git initgit init会在当前目录下创建一个隐藏的.git文件夹这个文件夹就是本地仓库的核心所有版本记录都存在里面。注意不要手动去改.git文件夹里的任何东西否则可能把仓库搞坏。如果是把已有的作业文件夹变成仓库直接进入那个文件夹执行git init就行。执行完之后用git status查看状态你会看到所有文件都显示为红色表示它们还没有被Git跟踪。这里有一个容易忽略的点git init之后Git会默认创建一个叫master或main的分支。不同版本的Git默认分支名可能不同较新的版本倾向于用main。你可以用git branch查看当前分支名。如果老师或平台要求用特定的分支名可以用git branch -M 分支名来重命名。2.3 关联远程仓库并完成首次推送本地仓库建好之后如果作业需要提交到远程仓库你还需要在代码托管平台上创建一个远程仓库然后把两者关联起来。在平台上创建仓库时通常可以选择“公开”或“私有”。交作业的话如果老师没有特别要求公开建议选私有避免同学之间互相看到代码。创建完成后平台会给你一个仓库地址形如https://xxx.com/用户名/仓库名.git。关联远程仓库的命令是git remote add origin 你的仓库地址这里的origin是远程仓库的默认别名你也可以叫别的名字但origin是约定俗成的建议不要改。关联之后可以用git remote -v查看是否关联成功。首次推送之前通常需要先做一次提交然后执行git push -u origin main-u参数的作用是把本地分支和远程分支关联起来以后你再推送同一个分支时直接git push就行不用再指定远程仓库和分支名。如果远程仓库是空的这一步会直接把本地提交推上去如果远程仓库里已经有内容比如创建时自动生成了说明文件你可能需要先git pull合并一下再推送。提示首次连接远程仓库时平台通常会要求身份验证。现在多数平台推荐使用访问令牌而不是账号密码具体方式各平台文档里都有说明按照指引操作即可。令牌要妥善保管不要直接写在代码里或者提交到仓库中。3. 日常提交作业的完整工作流3.1 从修改文件到暂存的正确姿势假设你已经写好了作业的一部分现在想把它存一个档。第一步是查看当前状态git status这个命令会告诉你哪些文件被修改了、哪些是新增加的、哪些已经放进了暂存区。红色表示还没暂存绿色表示已经暂存。养成每次操作前先看一眼状态的习惯能避免很多误操作。确认要提交的文件后用git add把它们放进暂存区git add homework.py如果这次改了好几个文件想全部暂存可以用git add .但我要提醒一句git add .虽然方便但容易把不该提交的文件也加进去比如临时文件、缓存文件、包含个人配置的文件。更稳妥的做法是一个一个指定文件名或者先配置好忽略规则后面会讲。暂存之后再用git status确认一下确保暂存区里只有你想提交的内容。如果发现加错了文件可以用git restore --staged 文件名把它从暂存区撤出来工作区的修改不会丢失。3.2 写好提交说明的实用技巧暂存完成后就可以提交了git commit -m 完成第一题实现斐波那契数列-m后面跟的是提交说明。很多人不重视这个说明随便写个“更新”或者“提交”结果过几天自己都看不懂当时改了什么。提交说明是写给自己和老师看的值得花几秒钟认真写。我的习惯是用一个简短的动词开头说明这次提交做了什么。比如“完成”“修复”“重构”“添加”“删除”。如果一次提交涉及多个点可以用分号隔开。如果作业有明确的题目编号把编号也写进去方便对照。如果提交说明比较长可以不加-m直接执行git commitGit会打开一个编辑器让你写多行说明。第一行是简短摘要空一行之后可以写详细描述。这种格式在查看历史时更清晰。还有一个技巧如果你改了文件但只想提交其中一部分内容比如一个文件里改了两个不相关的函数可以用git add -p进入交互式暂存模式Git会一块一块地问你要不要暂存。这个功能刚开始用可能觉得繁琐但熟练之后非常有用。3.3 推送到远程仓库与验证结果本地提交完成后就可以推送到远程仓库了git push如果之前已经用-u关联过分支直接这样就行。推送成功后去平台上刷新页面应该能看到刚才的提交记录和文件内容。有时候推送会被拒绝提示远程仓库有本地没有的更新。这通常发生在你在平台上直接修改了文件或者多人协作时别人先推送了。解决办法是先拉取再推送git pull git pushgit pull会把远程的更新合并到本地。如果合并过程中出现冲突Git会提示哪些文件有冲突你需要手动打开这些文件找到和标记的部分决定保留哪边的代码然后重新add和commit。注意交作业场景下如果老师要求你从某个模板仓库开始做通常需要先克隆老师的仓库而不是自己新建。克隆命令是git clone 仓库地址它会把远程仓库完整地复制到本地包括所有历史记录。4. 分支管理与版本回退实战4.1 用分支隔离不同题目的修改分支是Git里非常强大的一个概念但初学者往往觉得用不上。其实在交作业这个场景里分支就能帮上忙。假设一次作业有三道题你可以为每道题建一个分支做完一道合并一道这样每道题的修改互不干扰。创建并切换到新分支git checkout -b question1这个命令相当于git branch question1加上git checkout question1新建分支并立刻切过去。在question1分支上完成第一题、提交然后切回主分支git checkout main git merge question1git merge会把question1分支上的修改合并到main分支。合并完成后可以删掉已经没用的分支git branch -d question1用分支的好处是如果第一题做错了需要重做你可以在不影响其他题目的情况下单独处理。而且合并到主分支之后主分支上的历史记录会清晰地显示“合并了第一题”这个节点。4.2 查看历史与回退到指定版本查看提交历史用git log默认会显示每个提交的完整哈希值、作者、日期和说明。如果觉得太啰嗦可以用git log --oneline这样每个提交只显示一行前面是短哈希值后面是说明看起来清爽很多。想看到分支合并的图形化展示可以加--graph参数。如果发现某次提交改错了想回退有几种不同的做法。最温和的是git revert它会创建一个新的提交来抵消指定提交的修改历史记录保留完整git revert 提交哈希值另一种是git reset它直接把当前分支的指针移到指定的提交后面的提交就像没发生过一样。git reset --soft只移动指针暂存区和工作区不变git reset --hard则连工作区的内容也一起回退这个操作会丢失未提交的修改用之前一定要确认清楚。对于交作业来说如果只是想把某个文件恢复到之前某个版本的样子可以用git checkout 提交哈希值 -- 文件名这样只恢复指定文件不影响其他文件也不会移动分支指针相对安全。4.3 处理合并冲突的实操思路合并冲突是初学者最怕遇到的情况但其实处理起来有固定的套路。冲突通常发生在两个分支修改了同一个文件的同一部分Git不知道该保留哪个版本。当git merge提示冲突时打开冲突文件你会看到类似这样的标记 HEAD print(这是当前分支的代码) print(这是要合并进来的分支的代码) question1 HEAD和之间是当前分支的内容和之间是要合并进来的分支的内容。你需要手动决定最终保留什么把标记行删掉留下正确的代码。如果两边的内容都需要就把它们都保留调整成合理的顺序。改完之后重新git add这个文件然后git commit完成合并。如果想放弃这次合并可以用git merge --abort回到合并前的状态。提示处理冲突时不要慌也不要直接删掉标记行就完事。先理解两边分别改了什么再决定怎么合并。如果实在拿不准可以把冲突文件的内容复制出来分别看看两个版本想清楚再动手。5. 常见问题排查与避坑经验5.1 提交错文件或漏提交的补救方法最常见的失误有两种一是把不该提交的文件提交了二是该提交的文件忘了加进去。如果刚提交完就发现漏了文件可以先把漏掉的文件git add然后执行git commit --amend这个命令会把暂存区的内容追加到上一次提交里同时允许你修改提交说明。注意如果这次提交已经推送到远程仓库了--amend之后推送需要加--force而强制推送在多人协作时可能覆盖别人的修改要谨慎使用。如果发现提交了不该提交的文件比如一个包含密码的配置文件可以用git rm --cached 文件名这会把文件从Git的跟踪中移除但保留在工作区里。然后把这个文件名加到.gitignore文件中再提交一次。.gitignore是一个纯文本文件里面每一行写一个要忽略的文件或目录模式。比如__pycache__/ *.pyc .env config.ini这个文件本身应该被提交到仓库里这样所有协作者都能共享同一套忽略规则。5.2 推送被拒绝的几种典型情况推送被拒绝是最让人头疼的问题之一但原因通常就那么几种。第一种是远程仓库有本地没有的提交。解决办法是先git pull解决可能的冲突后再git push。第二种是权限问题。如果你对远程仓库没有写权限推送会被拒绝。交作业时如果老师给你的是只读权限的仓库你需要先fork到自己账号下再推送到自己的仓库然后发起合并请求。第三种是分支名不匹配。比如你本地在main分支但远程仓库的默认分支是master推送时就会找不到对应分支。可以用git branch -a查看所有分支确认本地和远程的分支名是否一致。第四种是网络问题导致的推送中断。这种情况重新推送一次通常就好了。如果反复失败可以检查一下仓库地址是否正确、网络连接是否正常。5.3 常见问题速查表问题现象可能原因解决办法git status显示大量未跟踪文件没有配置忽略规则创建.gitignore文件并添加忽略模式提交时提示“请配置用户信息”没有配置user.name或user.email执行git config --global配置推送时提示“拒绝更新”远程有本地没有的提交先git pull再git push合并时出现冲突标记两个分支改了同一处手动编辑冲突文件后重新提交中文文件名显示为乱码没有关闭路径转义配置core.quotepath false误提交了敏感文件没有忽略规则或误操作git rm --cached移除并加入忽略想撤销最近一次提交提交内容有误git reset --soft HEAD~1回退但保留修改5.4 我踩过的几个坑和对应经验第一个坑是在错误的分支上做修改。有一次我在main分支上直接改代码改到一半才想起来应该新建分支。这时候如果直接切分支未提交的修改会跟着过去容易搞乱。正确的做法是先把当前修改暂存起来git stash切到正确的分支后再恢复git stash pop。git stash这个命令我后来用得非常多它就像一个临时储物柜能把当前未提交的修改先存起来让工作区变干净方便你切换分支或拉取更新。第二个坑是提交说明写得太随意。刚开始用Git时我都是写“update”“fix”这种结果过了一周回头看历史完全想不起来每次改了什么。后来改成写清楚“完成了什么功能”或“修复了什么问题”查看历史时一目了然。如果作业有题目编号把编号也写进去比如“题2实现冒泡排序并添加测试”。第三个坑是忘记拉取就推送。有几次在平台上直接改了文件本地没同步推送时被拒绝。后来养成了习惯每次开始写作业之前先git pull确保本地是最新的推送之前再git status确认一下状态。这个习惯帮我避免了很多不必要的冲突。第四个坑是把虚拟环境文件夹提交了。Python项目通常会建一个虚拟环境里面文件成千上万提交上去既慢又没必要。后来在.gitignore里加上虚拟环境文件夹的名字问题就解决了。如果你用的是venv忽略规则写venv/如果是conda环境通常不在项目目录里不用特别处理。6. 高效提交作业的进阶建议6.1 用提交频率展示学习过程有些老师会看提交历史来判断学生的学习态度和解题过程。如果你的提交记录是一条平滑的曲线——每天都有几次提交说明你在持续地推进作业如果只有最后一天一个巨大的提交那大概率是赶出来的。我的建议是完成一个小功能就提交一次。比如你写了一个函数并且测试通过了就提交一次又写了一个函数再提交一次。这样提交历史就像一篇日记记录了你从无到有的完整过程。即使最后作业没做完老师也能看到你确实花时间做了。提交说明也可以写得更有信息量。比如“完成数据读取部分测试了三种输入格式”比“更新代码”要好得多。如果某次提交是为了修复一个bug可以写“修复了输入为空时的报错问题”。这些细节能让老师感受到你的思考过程。6.2 用标签标记最终提交版本当作业全部完成、准备提交给老师时可以给最终版本打一个标签git tag -a v1.0 -m 作业最终提交版本标签和分支不同它不会移动永远指向那个特定的提交。老师如果想知道你最终交的是哪个版本看标签就行不用在一堆提交里找。打完标签后推送标签到远程仓库git push origin v1.0如果之后又改了代码可以打v1.1、v1.2这样的标签表示修订版本。标签让版本管理更清晰也方便老师对照评分。6.3 把Git变成日常习惯的几个小技巧第一个技巧是把git status当成条件反射。每次打开终端进入项目目录第一件事就是git status看看当前是什么状态。这个习惯能让你随时知道自己在哪、改了什么、有什么没提交。第二个技巧是用别名简化常用命令。比如git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit配置之后git st就等于git status能省不少打字时间。别名可以根据自己的习惯来定没有标准答案。第三个技巧是定期查看提交历史。git log --oneline --graph能让你看到整个项目的演进过程。有时候你会发现自己某次提交引入了一个问题通过历史记录能快速定位到是哪次改动导致的。第四个技巧是在提交之前先跑一遍代码。Git只负责记录你提交了什么不负责检查代码能不能跑。养成提交前运行一遍的习惯避免把报错的代码提交上去。如果作业有测试用例提交前跑一遍测试确保通过再提交。6.4 从交作业延伸到真实项目协作交作业用到的Git技能其实已经覆盖了真实项目协作的大部分基础操作。工作区、暂存区、本地仓库、远程仓库这套模型在任何规模的团队里都是一样的。分支、合并、冲突处理这些操作在多人协作时会更频繁地用到。区别在于真实项目里通常有更严格的流程规范比如提交说明的格式要求、分支命名的约定、代码审查的环节。但这些规范都是建立在基础操作之上的你把基础打牢了适应规范只是时间问题。另外真实项目里还会用到一些交作业场景不太涉及的功能比如git rebase整理提交历史、git cherry-pick挑选特定提交、git bisect二分查找引入bug的提交。这些功能等你把基础用熟了可以逐步了解。不用一开始就追求全都会先把add、commit、push、pull这四个命令用成肌肉记忆其他的遇到再学。我个人在实际操作中的体会是Git这东西光看教程是学不会的必须自己动手折腾。建一个测试仓库随便改随便提交把各种命令都试一遍搞坏了就删掉重来。折腾几次之后那些概念自然就清晰了。交作业正好是一个低风险的练习场景用坏了也不影响什么放心大胆地去试就行。
阅读完成 · 觉得有帮助?