
目录Reference一、git安装ubuntu二、理论基础2.1 git记录的是什么2.2 三棵树2.3 git工作流程三、查看状态四、回到过去reset checkout4.1 reset4.2 checkout4.3 checkout reset 区别五、修改最后一次提交、删除文件和重命名文件5.1 修改最后一次提交5.2 删除文件5.2.1 rm5.2.2 git rm5.2.3 git rm -f 命令5.2.4 git rm --cached 命令5.2.5 常见问题5. 重命名文件六、创建和切换分支七、合并删除分支分支管理八、远程仓库九、ithub9.1 添加远程库9.2 设置Github秘钥十、GiteeReference《极客Python之Git实用教程》廖雪峰Git教程Git使用教程(小甲鱼)git restore 和 git restore --staged 的区别一、git安装ubuntu二、理论基础2.1 git记录的是什么如上如果每个版本中有文件发生变动Git 会将整个文件复制并保存起来。这种设计看似会多消耗更多的空间但在分支管理时却是带来了很多的益处和便利。2.2 三棵树你的本地仓库有 Git 维护的三棵“树”组成这是 Git 的核心框架。这三棵树分别是工作区域、暂存区域和 Git 仓库工作区的概念不仅包含你实际更改的文件还应当包括当前修改但未add存入暂存区的文件变化信息暂存区的作用则是临时存储文件的变化信息在git add file操作之后暂存区中将记录file文件上的修改信息。暂存区的存在更细化了时间节点要知道commit的往往是有重大改变的版本或者是在一次修改工作整体完成之后才使用commit。而在这之间需要保存的修改自然需要一个缓存区暂时存放。2.3 git工作流程(1) 在工作目录中添加、修改文件(2) 将需要进行版本管理的文件放入暂存区域(3) 将暂存区域的文件提交到 Git 仓库。因此Git 管理的文件有三种状态已修改modified、已暂存staged和已提交committed依次对应上边的每一个流程。工作区的文件 git add 后到暂存区暂存区的文件 git commit 后到版本库。git add filenamegit commit-mwhat you have donegit commit -am update information 等价于上面两个步骤三、查看状态git status:可以让我们时刻掌握工作区的状态git log命令显示从最近到最远的提交日志git diffgit diff如果git status告诉你有文件被修改过 git diff可以查看修改内容比较暂存区与工作目录git diff 快照 ID,快照 ID比较两个历史快照id1相比于id2做出了什么变化git diff 快照 ID:比较当前目录与git仓库快照的差异git diff --catched [快照ID]:比较暂存区域和git仓库快照vim使用基础移动命令j、k向下移动一行/向上移动一行f、b向下翻页/向上翻页d、u向下翻半页/向上翻半页跳转命令g、G跳转到第一行/跳转到最后一行 先输入数字如3再输入g表示跳转到该行如第3行搜索命令输入斜杠/或问号?,后面接搜索关键字区别斜杠/表示从当前位置向下搜索问号?表示从当前位置向上搜索。接着输入 n 表示顺着当前的搜索方向快速跳转到下个匹配的位置大写的 N 则是与当前搜索方向相反。退出和帮助在点点:后边输入 q表示退出 diff输入 h 表示进入帮助界面你会看到很多命令和功能输入 q 可以退出帮助界面。四、回到过去reset checkout1 引言HEAD指向的版本就是当前版本因此Git允许我们在版本的历史之间穿梭使用命令git reset --hard commit_id。穿梭前用git log可以查看提交历史以便确定要回退到哪个版本。要重返未来用git reflog查看命令历史以便确定要回到未来的哪个版本。2 撤销命令git commit --amend撤销上一次提交 并将暂存区文件重新提交; 详见5.1git checkout -- file拉取暂存区文件 并将其替换成工作区文件;从历史快照或者暂存区域中拷贝文件到工作目录 撤销对工作区修改这个命令是以最新的存储时间节点add和commit为参照覆盖工作区对应文件file这个命令改变的是工作区; 详见4.2git reset HEAD -- file拉取最近一次提交到版本库的文件到暂存区改操作不影响工作区; 清空add命令向暂存区提交的关于file文件的修改Ustage这个命令仅改变暂存区并不改变工作区这意味着在无任何其他操作的情况下工作区中的实际文件同该命令运行之前无任何改变; 当我们把工作区的某个文件弄乱了 我们就可以使用该命令 把版本库中的那个文件拉到暂存区 然后在拉回工作区; 详见4.1场景1当你改乱了工作区某个文件的内容想直接丢弃工作区的修改时用命令git checkout -- file。场景2当你不但改乱了工作区某个文件的内容还添加到了暂存区时想丢弃修改分两步第一步用命令git reset HEAD file就回到了场景1第二步按场景1操作。场景3已经提交了不合适的修改到版本库时想要撤销本次提交参考版本回退一节不过前提是没有推送到远程库。3参考Git 初接触 三 Git的撤销操作 git reset HEAD –4.1 resetGit Reset 三种模式1 问题有时候我们用Git的时候有可能commit提交代码后发现这一次commit的内容是有错误的那么有两种处理方法1、修改错误内容再次commit一次 2、使用git reset命令撤销这一次错误的commit第一种方法比较直接但会多次一次commit记录。而我个人更倾向第二种方法错误的commit没必要保留下来。2 基本概念git reset可以让HEAD这个指针指向其他的地方。例如我们有一次commit不是不是很满意需要回到上一次的Commit里面。那么这个时候就需要通过reset把HEAD指针指向上一次的commit的点。它有三种模式soft,mixed,hard具体的使用方法下面这张图展示的很全面了。回滚快照注快照即提交的版本每个版本我们称之为一个快照。现在我们利用 reset 命令回滚快照并看看 Git 仓库和三棵树分别发生了什么。执行git reset HEAD~命令注HEAD 表示最新提交的快照而 HEAD~ 表示 HEAD 的上一个快照HEAD~~表示上上个快照如果表示上10个快照则可以用HEAD ~10此时我们的快找回滚到了第二棵数暂存区域,第一次执行reset后Git仓库:第一次执行reset后三棵树:git reset HEAD~ 命令其实是 git reset --mixed HEAD~ 的缩写 --mixed 选项是默认的。git reset --soft HEAD~:保留工作目录并把重置 HEAD 所带来的新的差异放进暂存区; 命令就相当于只移动 HEAD 的指向但并不会将快照回滚到暂存区域。相当于撤消了上一次的提交commit。一不小心提交了后悔了那么你就执行 git reset–soft HEAD~ 命令即可此时执行 git log 命令也不会再看到已经撤消了的那个提交。默认git reset HEAD~命令其实影响了两棵树首先是移动 HEAD的指向将其指向上一个快照HEAD~然后再将该位置的快照回滚到暂存区域。保留工作目录并清空暂存区 工作目录的内容和 --soft 一样会被保留但和 --soft 的区别在于它会把暂存区清空,并把原节点和reset节点的差异的文件放在工作目录总而言之就是工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异都会被放进工作目录。git reset --hard HEAD~:重置stage区和工作目录; stage区和工作目录里的内容会被完全重置为和HEAD的新位置相同的内容。换句话说就是你的没有commit的修改会被全部擦掉。–mixed指令中将HEAD移动后指向的快照回滚到暂存区说法对吗不是应该把head回滚到工作区吗这里为什么说是暂存区继续上面的执行git reset --hard HEAD~回滚指定快照reset 不仅可以回滚指定快照还可以回滚个别文件。命令格式为git reset 快照 文件名/路径这样它就会将忽略移动 HEAD 的指向这一步因为你只是回滚快照的部分内容并不是整个快照所以 HEAD的指向不应该发生改变直接将指定快照的指定文件回滚到暂存区域。不仅可以往回滚还可以往前滚这里需要强调的是reset 不仅是一个“复古”的命令它不仅可以回到过去还可以去到“未来”。 唯一的一个前提条件是你需要知道指定快照的 ID 号。 那如果不小心把命令窗口关了不记得ID号怎么办 命令git reflog记录git的每一次操作的版本ID号 总结reset 命令回滚快照三部曲:1移动HEAD的指向–soft2. 将快照回滚到暂存区–mixed3. 将暂存区域还原到工作目录–hardgit reset --soft HEAD~:相当于撤销commit撤销错误的提交操作暂存区和工作区都是当前版本的内容git reset --mixed HEAD~:暂存区的内容是前一个版本的工作区是当前版本的想要回到当前版本必须先add再commitgit reset --hard HEAD~:会将工作目录中的最新文件覆盖掉危险操作git reflog:查看之前所有的版本号ID. HEAD指向的版本就是当前版本git reset ID: 回滚到指定快照版本git reset 版本快照 文件名/路径回滚到个别文件HEAD指针不会变Untracked files 说明存在未跟踪的文件下边红色的那个所谓的“未跟踪”文件是指那些新添加的并且未被加入到暂存区域或提交的文件。它们处于一个逍遥法外的状态但你一旦将它们加入暂存区域或提交到 Git 仓库它们就开始受到 Git 的“跟踪”。reset三种模式区别和使用场景区别–hard重置位置的同时直接将 working Tree工作目录、 index 暂存区及 repository 都重置成目标Reset节点的內容,所以效果看起来等同于清空暂存区和工作区。–soft重置位置的同时保留working Tree工作目录和index暂存区的内容只让repository中的内容和reset 目标节点保持一致因此原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files)。所以效果看起来就是工作目录的内容不变暂存区原有的内容也不变只是原节点和Reset节点之间的所有差异都会放到暂存区中。–mixed默认重置位置的同时只保留Working Tree工作目录的內容但会将 Index暂存区 和Repository 中的內容更改和reset目标节点一致因此原节点和Reset节点之间的【差异变更集】会放入WorkingTree工作目录中。所以效果看起来就是原节点和Reset节点之间的所有差异都会放到工作目录中。 实例结合GIT Reset 三种模式进行理解一git reset --soft保留工作目录并把重置 HEAD 所带来的新的差异放进暂存区此处把laugters.txt在工作目录相当于新增的这种变化这种情况放进暂存区二git reset 【--mixed】 HEAD^保留工作目录并清空暂存区工作目录的内容和 --soft 一样会被保留但和 --soft 的区别在于它会把暂存区清空,并把原节点和reset节点的差异的文件放在工作目录总而言之就是工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异都会被放进工作目录三git reset --hard HEAD^可以看到在 reset --hard 后所有的改动都被擦掉了。4.2 checkoutcheckout 命令有两种功能(1) 从历史快照或者暂存区域中拷贝文件到工作目录:git checkout -- file(2) 切换分支:git checkout branch 分支名一从历史快照或者暂存区域中拷贝文件到工作目录当给定某个文件名时Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行git checkout HEAD~ README.md命令会将上一个快照中的README.md文件复制到工作目录和暂存区域中如果命令中没有指定具体的快照 ID则将从暂存区域恢复指定文件到工作目录git checkout README.md命令git checkout -- readme.txt意思就是把readme.txt文件在工作区的修改全部撤销这里有两种情况一一种是readme.txt自修改后还没有被放到暂存区现在撤销修改就回到和版本库一模一样的状态二一种是readme.txt已经添加到暂存区后又作了修改现在撤销修改就回到添加到暂存区后的状态。总之就是让这个文件回到最近一次git commit或git add时的状态。撤销修改廖雪峰的官网有些朋友可能会问“上次看你在文件名的前边有加两个横杆–这次怎么就没有了呢”问得好Git 提醒你写成git checkout -- README.md的形式那是为了预防你恰好有一个分支叫做README.md那么它就搞不懂你要恢复文件还是切换分支了所以约定两个横杆–后边跟的是文件名。反过来说如果你确保你没有一个叫做README.md的分支你直接写git checkout README.md也是妥妥的没问题啦二 切换分支首先我们知道 Git 的分支其实就是添加一个指向快照的指针其次我们还知道切换分支除了修改 HEAD 指针的指向还会改变暂存区域和工作目录的内容。所以执行 git checkout 373c0 命令Git 主要就是做了下边这两件事当然事实上 Git 还做了更多4.3 checkout reset 区别(1) 恢复文件checkout 命令和 reset 命令都可以用于恢复指定快照的指定文件并且它们都不会改变 HEAD 指针的指向。它们的区别是 reset 命令只将指定文件恢复到暂存区域–mixed而 checkout 命令是同时覆盖暂存区域和工作目录。注意也许你试图使用git reset --hard HEAD~ README.md命令让 reset 同时覆盖工作目录但 Git 会告诉你这是徒劳此时 reset 不允许使用 --soft 或 --hard 选项。这样看来在恢复文件方面reset 命令要比 checkout 命令更安全一些。(2) 恢复快照reset 命令是用来“回到过去”的根据选项的不同reset 命令将移动 HEAD 指针–soft - 覆盖暂存区域–mixed默认- 覆盖工作目录–hard。checkout 命令虽说是用于切换分支但前面你也看到了它事实上也是通过移动 HEAD 指针和覆盖暂存区域、工作目录来实现的。那问题来了它们有什么区别呢下面开始划重点第一个区别是对于reset --hard命令来说checkout命令更安全。因为checkout命令在切换分支前会先检查一下当前的工作状态如果不是“clean”的话Git 不会允许你这样做而reset --hard命令则是直接覆盖所有数据。另一个区别是如何更新 HEAD 指向reset 命令会移动 HEAD 所在分支的指向而 checkout 命令只会移动 HEAD 自身来指向另一个分支。看文字你肯定懵我们举例说明。来大家先把刚才的例子改成下边这样执行 git checkout feature 命令可以看到只是 HEAD 指针跑到 feature 分支那儿去了。好我们执行 git checkout master 命令将其切回。现在执行 git reset --hard feature 命令五、修改最后一次提交、删除文件和重命名文件5.1 修改最后一次提交git commit --amend : 进入修改界面不会产生新的快照版本git commit --amend -m “说明信息” 直接进行重新提交不进入修改界面不会产生新的快照版本由于使用reset命令过于繁琐需要提交一个新的版本这里可以使用带 --amend 选项的 commit 命令即git commit --amendGit 会“更正”最近的一次提交。由于这里没有-m说明会进入以下页面这个界面其实只是让你编辑提交说明而已。如果不需要修改可以连续按下两个大写Z来退出或者按下:再输入q!退出Git会保留旧的提交说明。如果需要提交说明又不想用这么繁琐的方式输入git commit --ammend -m “新的提交说明” 即可。5.2 删除文件Git移除文件----git rm命令的使用git restore 和 git restore --staged 的区别5.2.1 rm在当前工作区有文件test.py并被git跟踪且有提交历史。运行如下命令1. 作用删除工作区的文件。rm test.py分析如下1test.py文件的状态是被删除。2此时工作区中的文件已经被删除3Changes not staged for commit 表明删除文件和新增文件对Git来说都是一种改变并没有将此改变提交到暂存区。如果要切实在commit提交中也要删除此文件那么就要首先将此种改变提交暂存区git add test.py然后完成此次提交git commit -m delete test.py另外如已经通过 rm 将某个文件删除掉了也可以再通过 git rm 命令重新将该文件从 git 的记录中删除掉。2. 结果删除了工作区的文件。5.2.2 git rm1. 作用 删除工作区文件并且将这次删除放入暂存区。2. 注意 要删除的文件是没有修改过的就是说和当前版本库文件的内容相同。通过纯粹的linux命令删除一个文件需要三个步骤1rm 删除文件。2将此种改变提交暂存区。3最后进行commit提交。使用git rm命令可以节省一步第二步代码如下git rm test.py查看一下此时状态分析如下1test.py处于deleted状态。2工作区中的文件已经被删除。3Changes to be committed表明此删除改变已经提交到暂存区如果要切实在commit提交中也要删除此文件就可以省略git add命令直接commit提交即可。git restore --staged 将文件从暂存区撤出但不会撤销文件的更改git resore 将不在暂存区的文件撤销更改git commit-mdelete test.py. 结果删除了工作区和版本库的文件因为暂存区不可能有该文件如果有意味着该文件修改后 git add 到暂存区那样 git rm 命令会报错如下面的情况。5.2.3 git rm -f 命令1. 作用删除工作区和暂存区文件并且将这次删除放入暂存区。2. 注意要删除的文件已经修改过就是说和当前版本库文件的内容不同。情况一test.py文件修改过还没 git add 到暂存区情况二test.py文件修改过且已经 git add 到暂存区可见文件修改后不管有没有 git add 到暂存区使用 git rm 命令删除都会报错。解决方法执行删除命令git rm -f test.py. 查看状态 :成功删除工作区和暂存区文件并且将这次删除放入暂存区5.2.4 git rm --cached 命令前面的rm和git rm都会将工作区的文件删除如果仅仅想让文件脱离Git的跟踪可以后面加–cached。这样工作区的文件不会删除仅删除暂存区中对应的文件。(从索引中删除文件。但是本地文件还存在 只是不希望这个文件被版本控制。)1. 作用 删除暂存区文件但保留工作区的文件并且将这次删除放入暂存区。执行删除命令git rm --cached README.mdreadme.md处于未跟踪状态也就是从暂存区删除。特别说明处于未跟踪状态只是没有存在于暂存区历史提交记录中的记录依然存在。然后提交成功删除了版本库文件。2. 结果删除了暂存区和版本库的文件但保留了工作区的文件。如果文件有修改并 git add 到暂存区再执行 git rm --cached 和 git commit那么保留的工作区文件是修改后的文件同时暂存区的修改文件和版本库的文件也被删了。5.2.5 常见问题问题一git rm 与 rm 的区别git rm 来删除文件同时还会将这个删除操作记录下来;rm 来删除文件仅仅是删除了物理文件没有将其从 git 的记录中剔除;提示即使你已经通过 rm 将某个文件删除掉了也可以再通过 git rm 命令重新将该文件从 git 的记录中删除掉。注意上述操作最后要执行git commit才真正提交到git仓库问题二不小心删除文件怎么办?现在从工作目录中手动删除 README.md 文件然后执行 git status 命令提醒使用 checkout 命令可以将暂存区域的文件恢复到工作目录文件就会重新返回。问题三那么如何彻底删除一个文件呢假如你不小心把小黄图下载到了工作目录然后又不小心提交到了 Git 仓库执行 git rm yellow.jpg 命令此时工作目录中的小黄图yellow.jpg已经被删除……但执行 git status 命令你仍然发现 Git 还不肯松手意思是说它在仓库的快照中发现有个叫 yellow 的东西但似乎在暂存区域和当前目录不见了此时可以执行 git reset --soft HEAD~ 命令将快照回滚到上一个位置然后重新提交Git 就不会再提小黄图的事儿了注意git rm 命令删除的只是工作目录和暂存区域的文件即取消跟踪在下次提交时不纳入版本管理5. 重命名文件六、创建和切换分支创建分支git branch 分支名切换分支:git checkout 分支名或者git switch name创建切换分支git checkout -b name或者git switch -c name查看当前分支git branch七、合并删除分支分支管理合并分支git merge 分支名删除分支git branch -d 分支名1 解决冲突当Git无法自动合并分支时就必须首先解决冲突。解决冲突后再提交合并完成。解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容再提交。用git log --graph命令可以看到分支合并图。2 分支管理策略在实际开发中我们应该按照几个基本原则进行分支管理首先master分支应该是非常稳定的也就是仅用来发布新版本平时不能在上面干活那在哪干活呢干活都在dev分支上也就是说dev分支是不稳定的到某个时候比如1.0版本发布时再把dev分支合并到master上在master分支发布1.0版本你和你的小伙伴们每个人都在dev分支上干活每个人都有自己的分支时不时地往dev分支上合并就可以了。所以团队合作的分支看起来就像这样Git分支十分强大在团队开发中应该充分应用。合并分支时加上--no-ff参数就可以用普通模式合并合并后的历史有分支能看出来曾经做过合并而fast forward合并就看不出来曾经做过合并。3 BUG 分支修复bug时我们会通过创建新的bug分支进行修复然后合并最后删除当手头工作没有完成时先把工作现场git stash一下然后去修复bug修复后再git stash pop回到工作现场在master分支上修复的bug想要合并到当前dev分支可以用git cherry-pick commit命令把bug提交的修改“复制”到当前分支避免重复劳动。4 Feature分支开发一个新feature最好新建一个分支如果要丢弃一个没有被合并过的分支可以通过git branch -D name强行删除。5 多人协作查看远程库信息使用git remote -v* 本地新建的分支如果不推送到远程对其他人就是不可见的从本地推送分支使用git push origin branch-name如果推送失败先用git pull抓取远程的新提交* 在本地创建和远程分支对应的分支使用git checkout -b branch-name origin/branch-name本地和远程分支的名称最好一致建立本地分支和远程分支的关联使用git branch --set-upstream branch-name origin/branch-name* 从远程抓取分支使用git pull如果有冲突要先处理冲突。八、远程仓库九、ithub先有本地库后有远程库的时候如何关联远程库。方法如下9.1 添加远程库1.在本地目录下关联远程repository git remote add origin gitgithub.com:git_username/repository_name.git2.取消本地目录下关联的远程库gitremote remove origin查看远程仓库为了确认远程仓库是否已正确添加你可以使用以下命令查看所有配置的远程仓库git remote-v关联后使用命令git push -u origin master第一次推送master分支的所有内容此后每次本地提交后只要有必要就可以使用命令git push origin master推送最新修改9.2 设置Github秘钥能够推库的必要操作Referencehttps://www.cnblogs.com/long5683/p/10629235.htmlgithub的SSH配置如下(一) 设置Git的user name和email第一节git 的安装git config --global user.name AmyOrzgit config --global user.email youremailgmail.com(二) 生成SSH密钥过程(1) 查看是否已经有了ssh密钥cd ~/.ssh如果没有密钥则不会有此文件夹有则备份删除(2) 生成密钥$ssh-keygen -t rsa -C “youremailgmail.com”按3个回车密码为空。最后得到了两个文件id_rsa和id_rsa.pubgedit id_rsa.pub打开3在github上添加ssh密钥这要添加的是“id_rsa.pub”里面的公钥。打开https://github.com/ 在settings里面点击SSH keys。随便输入title复制id_rsa.pub里面的内容到key。就设置成功了。十、Gitee[git上传代码至gitee仓库](https://www.cnblogs.com/must-grow/p/12790900.html全新Ubuntu环境拉取remote仓库文件进行开发一、环境准备Ubuntu 首次配置# 1. 安装 Gitsudo apt update sudo apt install git-y# 2. 设置全局用户名和邮箱与 Gitee 一致git config--global user.name你的Gitee用户名git config--global user.email你的邮箱example.com# 3. 生成 SSH 密钥一路回车ssh-keygen-t ed25519-C你的邮箱example.com# 4. 复制公钥并添加到 Gitee 设置 → SSH公钥cat~/.ssh/id_ed25519.pub二、克隆仓库到本地# 创建并进入工作目录可选mkdir ~/myprojects cd ~/myprojects# 使用 SSH 方式克隆确保公钥已添加git clone gitgitee.com:gavynlee/leetcoding.git# 进入项目目录cd leetcoding三、修改代码并本地提交# 编辑文件例如修改 README.md 或代码vim README.md# 添加所有更改到暂存区git add.# 提交到本地仓库附带注释信息git commit-m描述你的修改例如更新算法解法四、远程推送git push origin master报错fatal:origindoes not appear to be a git repository解决手动添加远程仓库地址git remote add origin gitgitee.com:gavynlee/leetcoding.git暴力推送git push-f origin master-f–force强制用本地内容覆盖远程 master 分支忽略远程已有的不同提交。这次成功了因为远程的提交被本地内容替换掉了。⚠️ 关于强制推送的重要提示你这次成功因为该仓库可能是个人仓库远程多出的提交不重要或者你已知晓。在团队协作中应避免-f因为它会永久丢失远程上的那些提交造成别人拉取时混乱常规安全流程先 git pull 合并再 git push。只有在确定远程提交可以抛弃时才用 -f。实操举例后续操作git add.git commit-m信息git pull origin master# 养成先拉取的习惯git push origin master# 或直接用 git push若已关联在Gitee上创建项目如果在使用命令git remote add时报错这说明本地库已经关联了一个名叫origin的远程库此时可以先用git remote -v查看远程库信息;可以看到本地库已经关联了origin的远程库并且该远程库指向GitHub。我们可以使用git remote rm/remove origin删除已有的GitHub远程库;最后再关联Gitee的远程库注意路径中需要填写正确的用户名