git部分关键点说明
【git resetgit revertgit checkout】git reset与revert一般用来撤销commit或push非特殊情况不得已时建议不用影响版本统一管理尤其是多人书写的分支。git reset针对“工作区、暂存区、索引区”倒序覆盖代码默认表示git reset --mixed都可以后边再加个“空格commitId”来指定特别的如果是HEAD就等于没写[注意跟HEAD^不同]做两件事一是索引区退回到指定id二是进而让暂存区退回如果不是mixed而是soft只做一件事就是索引区退回如果不是mixed而是hard多做一件事亦即第三是把工作区也覆盖掉所以hard最危险“覆盖”包括“未add的文件”其次一般自己的不确定要不要的代码最好先扔到一个分支上后续再详细整理。语义说完说语法此处commitId可以用HEAD处理直接git reset HEAD等同git reset但如果是HEAD^则代表索引区退回一次如果HEAD^^就是退回两次也可用HEAD2依次类推如果前述命令后接“双横杠空格”可指定特定文件的处理即“-- fileName”此处双横杠空格的意义在于指定文件可以避免双横杠的其他特定参数语义而转为“特定的文件名”语义这个语法据说来源于Linux的双横杠空格。【顺带一提】【start】git reset与git commit --amend均为“有可能”如果相对远程分支发生了索引退回会引发推送push到远程分支时的异常即commit-id即sha1码等不一致引发的异常亦即no-fast-forward此时当然只能用git push -f才能强行推送因此应坚决避免因为变基了即改变远程索引链。注一如果此处处理前无人提交则远程自动合并处理否则远程有可能暂时不处理之可能需要手动告知git reset --hard origin/master该情况没有亲身体验。注二强推并非毫无用处确认团队无人pull的情况下合理的review情况下使用强推可以帮助维护git目录树的整洁如果有其他人在当事人变基前已经pull过了并继续开发了此时其他人想push肯定不可能正常push得先再pull一次但此时会产生一个merge commit毕竟本地、远程已经有了不同的基准点当然要merge此时是基于远程的新基准点。【end】git revert意义在于回退一般是后接“空格版本号”代表将该版本发生的事撤销当然可以用“空格HEAD”。但是注意revert的意思是“还原”。深入理解的前提是操作的对象是两个提交块。正常是新的提交块“基于旧块发生了改变”revert则把“这些改变恢复到旧块的内容”。而且。注意revert与reset都可以回退但语法略有不同前者是“要撤掉该commitId的改变以达成回退”后者是“”直接回退到该commitId“reset撤销的其实是指定commitId之后的commitId的改变。因为revert处理的“点”细化到文件内容本身因此从能力上看比reset能做的事更多不代表建议使用不仅可以类似reset一般以git revert HEAD2的方式回退最近两次先最近一次再倒数第二次会有两条commit记录到倒数第三次也可以reveert commitId的方式退掉特定版本的操作但是并没有处理过“如果该文件在后续版本对应位置又发生修改”的情况但是一般而言这样没意义啊一般不都是退回特定文件的最新修改吗。再说下特定语法1.默认-eedit即进入编辑commit标记信息的编辑框2.可以像reset回退最近一个或多个版本git revert可以任意回退历史上的一个或一段版本号git revert commitId或git revert commit1..commit2区间时是左开右闭即不包括commit1而包括2当然也是多条commit3.可以-n如果对第2条多个commit比较厌烦的话不会自动提交多个commit而是执行后由自己手动提交如果revert强烈建议-n具体未使用请参照【Git - git-revert Documentation 与 git 版本回退方法 - little_ab - 博客园 与 git revert HEAD - 盘思动 - 博客园 或 https://zhuanlan.zhihu.com/p/229121771】其他说明1.push推送的不光是修改内容很重要的另外一个是“推送版本或推送基点”亦即“版本链的关系信息”2.reset是对“版本块”的处理目标对象其实是版本链而revert是针对“真正的修改内容”本身操作也是一个版本并没有跳出版本正常管理流程3.请基于第1点理解第2点4.很多时候git的处理是要参考多个版本点的特别是不同分支情况下。git checkout用来拿索引区的内容覆盖掉暂存区与工作区不涉及前两者“回退”的“强大功能”。作用有限但有用1.加“空格分支名”切换分支更新对应HEAD并拿索引区覆盖暂存区、工作区2.加“双横杠空格fileName”用暂存区覆盖工作区取消未add的修改也可以改为加“branch2双横杠空格fileName“当前branch不变仅仅把branch2分支的fileName拿来覆盖暂存区、工作区3.加“双横杠空格点”即“-- .”一般是简写一个点用暂存区覆盖工作区checkout最危险命令个人常与“git reset HEAD”合用先覆盖暂存后覆盖工作当然也可直接-- hard同样意义同样危险一般本地随便改点东西看效果后恢复使用中间穿插git status看文件差异一定要多看看差异毕竟危险命令。【git diff】顺便说下git diff比较简单。本身代表与最近“commit”内容的对比如果暂存区有内容就“工作区vs暂存区”否则“工作区vs索引区[index或head无所谓怎么称呼了]加headgit diff head就是“工作区vs索引区”加--cached注意两个横杠-就是“暂存区vs索引区”。感想很多命令在官网上说明的还真不够细毕竟简单几个单词就能做很多事官网懒得举例有时原文不太明确而翻译又跟不上时还是得多看看网上用例并亲自对比底层逻辑。***********************************************************************************************git merge 与 git rebase本质功能一致都是把目标分支合并到当前分支只不过合并的方式不同。git log 与git reflog 本质功能一致都是看日志但是log只能查看还在“关系链”中的版本而reflog可以查看“已经被删除的版本”只要这个版本还处在游离状态未消失。***********************************************************************************************【git fetch】顺便说下git fetch用于将远程仓库Repo更新至本地仓库Repo同时将相应/所有分支的FETCH_HEAD更新至远程的最新如果本地Repo没有该分支则会创建注意只是仓库分支不是“本地可编辑分支”。git fetch origin dev:local_dev可用于将远程origin只是远程在本地的别名的dev分支在本地Repo创建后更新至最新进而创建本地可编辑分支local_dev与之类似的是git checkout -b local_dev origin/dev但后者只是从本地Repo中拿到数据并据此创建一个可编辑分支local_dev与真正的远程Repo无关因此本地repo无dev则不可checkout -b创建但是一旦有即使无网也可创建。% git fetch origin dev ……………… * branch dev - dev * [new branch] dev - origin/dev % git fetch origin dev:dev ……………… * [new branch] dev - dev * [new branch] dev - origin/dev % git checkout -b dev origin/dev Branch dev set up to track remote branch dev from origin. Switched to a new branch dev对于上述fetch与checkout的语法区别点有三1.主宾刚好相反前To后From2.前者To用冒号‘:’后者From用斜杠‘/’3.前者不切换分支后者会切换至新创建的分支。【git checkout】顺便说下checkout拉远程分支这事的细节其中一个步骤是创建本质上分为三大块创建、填充内容、跟踪远程分支。创建与填充基本不会分开除非是纯粹创建git branch abc但是这样无中生有在团队研发中没啥意义因此与“跟踪远程分支”也可以认为是两大块可以分别对应两个命令git pull origin dev:local_dev以及git branch --set-upstream-toorigin/dev local_dev。【另注针对“跟踪远程分支”功能也可以使用git push -u origin local_dev但是该场景会“先跟踪后push”不是纯粹的“跟踪”不够灵活】两种方式都可以用于“本地分支与远程分支名称不同“但场景。如果与远程分支名称相同也可以用git checkout --track origin/dev。fetch有一个与之刚好类似语法的命令push即git push origin local_dev:dev创建了新分支的情况下使用该命令将新建分支local_dev推送至远程Repo[其实也包括本地Repo]此处本地分支在前冒号均代表TO的意义。另例可以用“git push origin :dev”来删除远程分支dev。***********************************************************************************************【git pull --rebase】顺便说下承接前文git fetch说明git pull --rebase。git pull git fetch git merge。git pull --rebase git fetch git rebase。git merge ***是基于当前分支将***最近一段差异化的版本数据以“一个单独的全新版本数据”的形式添加到当前分支的最新节点。***分支自身不变。git rebase ***是基于当前分支将其与***最近相同的版本号节点这个基本点改为以“***的最新节点”为基本点re base而且此时***上差异化的版本信息已经被拿到当前分支了是基于当前分支原基本点的然后让当前分支差异于***的部分始于新基本点。***分支自身仍然不变但是当前分支近似于“将原节点链从原基本点断开中间加入***上的差异版本数据”当然断开后的后一段可能会因为与差异数据的冲突而发生类似于merge的操作。大胆推测由于是类似于“断开后中间新加”则断开后一段的节点数不变则merge的过程是“基于新基本点每一个节点都要重新校验/merge”***********************************************************************************************【特定场景】1、已add、commit但因系统原因无法push需撤回修改commit先“ git reset --soft HEAD~1 ”撤回至暂存区再“ git reset ”撤回至工作区。2、基于当前分支创建新分支包含远程先基于当前分支执行“ git checkout -b 新分支名 ”再把新分支推上去“ git push origin 新分支名:新分支名 ”