keyipatience:个人主页作者简介C/C后端开发学习者专栏传送门《c》《linux》《c高阶数据结构》《c数据结构与算法》《前端学习》⭐️patience is key in lifeGit 撤销修改情况 1只改了文件没有 add修改只在工作区文件改坏了还没 add想撤销这一轮改动恢复到最近一次 add /commit 的样子 命令git checkout -- ReadMe # 新版git等价推荐写法 git restore ReadMe重点--不能省 如果写成git checkout ReadMegit 会理解成【切换到名叫 ReadMe 的分支】含义完全变了。作用 直接把工作区的改动抹掉文件变回暂存区 / 版本库里保存的样子刚才新增的内容直接消失。风险这个操作直接丢掉你工作区的修改无法找回谨慎使用情况 2已经 add但是还没有 commit修改在暂存区你已经git add ReadMe修改进到暂存区了现在后悔想撤出来 分两步走先把修改从暂存区撤回到工作区git reset HEAD ReadMe # 等价 git reset --mixed HEAD ReadMe--mixed是默认参数可以省略 //底层理解HEAD代表当前最新的 commit 版本库快照因为还有没有commit所以回退到当前最新的commit版本就是把 暂存区stage清空执行后效果暂存区清空文件的内容不变改动重新回到工作区接下来二选一改一改重新git add不想要了用git checkout -- ReadMe/git restore ReadMe删掉工作区改动情况 3已经 add commit修改提交进版本库了已经 commit生成一条版本记录现在想要撤销这次提交重要前提这个 commit 还没有 push 推送到远程仓库如果已经 push 到远端不能随便用--hard回退后面学远程会讲命令git reset --hard HEAD^HEAD^当前版本的上一个 commit--hard同时改动三处版本库指针、暂存区、工作区执行完HEAD 指针挪到上一个版本暂存区清空工作区直接变成上个版本的样子本次 commit 写的内容本地消失。一张汇总表场景状态目标命令1修改仅在工作区未 add丢掉工作区修改git checkout -- 文件名/git restore 文件名2已经 add未 commit取消暂存退回工作区git reset HEAD 文件名2 续取消暂存后想彻底删掉修改丢掉工作区修改git checkout -- 文件名3add commit未 push 远程回退到上一个版本删掉本次提交git reset --hard HEAD^文件名和HEAD系列分清楚写HEAD撤回提交管整条记录写文件名只取消 add只管这一个文件不碰提交想撤回【整个 commit 提交】后面写HEAD、HEAD^、一串 commit 哈希号作用把这一次提交给撤掉改提交历史。这里不带文件名管的是整条提交记录。git reset --soft HEAD^ git reset --hard HEAD^后面写文件名git reset [HEAD] file2.txt//[HEAD可以省略]刚才git add file2.txt加到暂存区了现在把它拿出来。不会撤销 commit不会改动提交历史Git 删除文件在 git 眼里删除文件 也是一种修改需要 add /commit 记录这个删除动作直接用 linux 的rm file5只删工作区rm file5效果本地磁盘工作区file5 删掉了版本库、暂存区里还保留这个文件git status提示deleted: file5红色Changes not staged for commit问题git 只是发现你在本地删了但是还没有把 “删除这件事” 登记到版本库里。 现在分两条路删错了 确实要删掉情况 A删错了想要恢复回来刚才只是rm file5还没执行git rm、没 commit 用之前学过的撤销工作区修改命令git checkout -- file5 # 新版等价git restore file5从版本库把 file5 拿回来恢复到工作区ls 又能看到 file5 了。情况 B确实想要把文件从版本库删掉git rm file5它一次性做两件事删除工作区的 file5如果还在的话把【删除 file5】这个动作加到暂存区git rm≠ linux 的 rm linux rm只动本地磁盘git 不知情git rm同时操作工作区 暂存区告诉 git我要删除这个文件然后必须 commit这个删除才正式写入版本库git commit -m deleted file5文件已经加到暂存想只从暂存区删掉、本地保留不是真删文件git rm --cached file5本地磁盘 file5还在只把它从暂存区 / 版本追踪里移除一般用来取消跟踪比如误 add 了大文件和reset效果一样Git 分支基础分支 平行宇宙主线master是一条时间线从某个提交点分出新分支就开出一条独立时间线分支之间互不干扰可以在不同分支写不同代码后面还能合并。例子master 主线正常开发开新分支写新功能写完再合并回主线。master和HEADmaster指向最新提交HEAD指向当前所在分支只有一个master是主分支指针指向这个分支上最新的一次提交。每commit一次master就自动向后移动一步。HEAD是当前所在分支的标记先指向master再由master指向最新提交。HEAD → master → 最新提交Git 创建分支git branch # 查看本地所有分支带 * 的是当前分支 git branch dev # 新建 dev 分支只创建不切换过去执行完git branch dev之后分支列表dev、* master→*代表 HEAD 当前在 master去.git/refs/heads/目录下看会多出一个dev文件ls .git/refs/heads/ cat .git/refs/heads/*master 和 dev 两个文件里存的 commit hash 值一模一样说明刚创建出来的 dev 和 master 指向同一个提交节点git branch dev只是新增一个指针不会复制文件、不会新建提交非常轻量这是 Git 分支高效的核心原因。Git 切换分支 分支独立提交切换分支命令git checkout dev # 等价新版推荐写法git switch dev执行后输出Switched to branch dev查看分支git branch*跑到 dev 前面代表当前分支是 dev底层验证 HEADcat .git/HEAD # 输出 ref: refs/heads/dev原理HEAD 指针移动指向 dev 分支原理图变化HEAD → devmaster 指针还停留在原来那个提交上不动。在 dev 分支做修改并提交vim ReadMe # 修改文件新增一行 write aaa for new branch git add . git commit -m modify ReadMe提交成功提示[dev 274bdce] modify ReadMe这个提交只会让 dev 分支指针向前移动一步master 指针原地不动不会跟着更新底层查看两个分支指向的 commit 哈希cat .git/refs/heads/dev # 拿到新的 commit id刚提交的 cat .git/refs/heads/master # 还是原来旧的 commit id核心两个分支指针现在指向不同提交节点两条分支历史开始分叉切回 master 分支现象新增内容消失git checkout master注意如果dev 改了文件不 add、不 commit切回 master新加内容还在因为这个改动还没有存入 Git 的版本库不在任何分支、不在任何提交里它只躺在你的本地工作目录。 Git 在切换分支的时候先检查工作区有没有未暂存、未提交的修改如果切换前后的两个分支这个文件没有版本差异Git 就不会覆盖你的改动直接把这份修改保留、带到目标分支查看 ReadMe刚才新增那一行不见了 再切回去 devgit checkout devReadMe 新增内容又回来了为什么会这样这次提交是在 dev 分支上做的master 分支根本没有包含这次提交切换到 master 时Git 将工作区恢复成 master 指向的那个旧提交对应的文件版本切换回 devGit 又把工作区换回 dev 最新提交的文件快照。Git 合并分支Fast-forward 快进合并承接前面流程dev 分支比 master 多了一次提交现在要把 dev 的改动合并进 master。整套命令流程git branch # 查看当前分支现在在 dev git checkout master # 先切到 master合并是【把别的分支合并到当前分支】 git merge dev # 将 dev 合并到 master输出关键信息Updating 16623e1..3740dce Fast-forward ReadMe | 1 1 file changed, 1 insertion()查看 ReadMemaster 里面也出现了 dev 新增的那一行内容。重点规则git merge [分支名]的含义把指定分支合并到【你现在所在的分支】所以合并前一定要先切到目标分支这里是 master。Fast-forward快进模式是什么原理图变化 合并前master 停在旧提交点dev 在 master 的正前方顺着一条线往前走了一次提交快进合并的时候Git不产生新的提交记录只是直接移动 master 指针所以我们不好区分到底是merge让指针移动一步还是在master分支上commit一次让指针移动让 master 指向和 dev 同一个提交节点。所以快进合并没有生成新提交merge 命令执行完就结束了不用再敲git commit。Git 删除分支命令git branch -d devd--delete安全删除分支。两个硬性规则1.不能删除当前所在的分支* 例子现在在 dev* dev执行git branch -d deverror: Cannot delete branch dev checked out at xxx2.正确做法先切到别的分支一般切 master/main再删git checkout master git branch -d dev-d安全删除的底层限制git branch -d是安全模式Git 会检查这个分支的所有提交是不是已经被别的分支合并、能访问到了。像如果dev已经合并进 master→ 可以-d删除如果 dev 独有的提交还没有合并进主分支直接-d会拒绝删除防止你丢提交大写-D强制删除危险git branch -D dev-D --delete --force不管分支有没有合并、有没有独有的提交直接删掉分支指针。Git 鼓励你使用分支完成某个任务合并后再删掉分支这和直接在 master 分支上工作效果是一样的但过程更安全。即开发新功能、改 bug新建 dev 分支干活测试没问题合并到主分支 master合并完成dev 使命结束删除它 好处master 全程保持干净稳定开发过程中的错误、半成品不会污染主分支