提高开发效率的git命令使用及vscode和sourceTree的对比使用

1,797 阅读14分钟

为什么分享?

  1. 在日常的代码开发过程中,专注业务开发和提升自己的同时,渐渐忽略了代码管理也是重要的技能之一
  2. 目前市场上的开发工具集成git管理工具,或专门git管理工具,都是基于git命令而开发出来的,熟悉了熟悉或了解源命令使用才能更加方便清晰的使用工具上集成的功能
  3. 在长期习惯了使用git集成工具下,大多数也只会使用基本的保存(add),提交(commit),推送(push),拉取(pull),回滚(reset),合并(merge),当然,学会这些已经能够正常的进行开发了,但是遇到一些commit管理的问题就有点束手无策,无法使用一些优雅的方式解决

分享的期望

  1. 能够更加的优雅的管理仓库代码和记录,颗粒度的commit和git提交规范的遵从能更方便的溯源
  2. 常在河边走,哪有不湿鞋,熟悉git命令的运用,增加项目开发中的容错率,提升开发效率

分享内容(正文)

stash

  1. 命令作用:
    • 保存本地修改,记录工作目录和索引的当前状态,并恢复工作目录以匹配头部提交,并且可以做多次存储
  2. 使用场景:
    • 在正常开发某个项目的时候,测试突然和你说线上有bug需要修复或者别的测试分支有bug需要修正,但这时候你开发的功能模块还未完成,无法切换分支,因为当前有文件改动,需要提交commit保持工作区干净才能切分支。由于情况紧急,你只有急忙 commit 上去,commit 信息也随便写了个“暂存代码”,于是该分支提交记录就留了一条黑历史...(真人真事,自己操作过也看过这种提交)
    • 自己曾经遇到很多次的问题,也犯过多次的错误,两个人同时对一个项目不同需求的开发,差不多时间提测,由于测试环境就那么几个,测试会提出两个人的分支合在一个新的测试分支进行测试,当测试提出bug的时候,正常流程是在自己的开发分支修正,然后再合进共同的测试分支给测试验证,这样的情况下很多时候就会出现把修复好的bug合并到test分支后经常会忘记切换到自己的开发分支,然后下一次测试在提bug的时候,就自然而然的在当前的test分支上更改了,要是当前的bug修复之后只是一点点文件改动还好,要是很多的话这时候就简直是裂开,只能在伴随着心里的一声喝骂声中把对应的丢该含泪复制出来,然后在切换回自己的开发分支一点一点的复制过去
  3. 使用方法:
    • git stash 存储当前文件改动,运行该命令,这时就可以自如的切换分支进行相关操作啦

    • git stash save ‘备注的内容’ 存储当前的文件改动,并添加存储备注

    • git stash apply 恢复最近一次存储的文件改动

    • git stash pop 恢复最近一次存储的文件改动,并将其存储记录删除

    • git stash list 列出所有的暂存记录

      stash list.png

      vscode查看储存列表 vscode_stash_list.png sourceTree查看储存列表 sourceTree_stash_list.png

    • git stash apply stash@{index} 恢复指定索引存储的文件改动

      stash apply.png

    • git stash pop @{index} 恢复指定索引存储的文件改动 并将其存储记录删除

    • git stash claer 清除所有的存储记录

    • git stash drop 删除最近一次的存储记录

    • git stash save ‘备注的内容’ 删除最近一次的存储记录 stash_save.png

reset --soft

  1. 命令作用:

    • 对已经commit的修改进行回退重新操作,并将 commit 的修改内容放回到暂存区 保持记录鲜明、干净的提交记录
  2. 使用场景:

    • 有的小伙伴在不知道stash命令的使用下,对出现开发到一半又遇到需要切分支修改问题的情况,代码又是只能先本地提交暂存(蝴蝶效应了这是?)然后切换分支去修改问题,再切换的时候只能继续开发,开发完之后提交至仓库,就会出现两条commit,一条为之前的暂存,一条为最近的提交说明,就出现了一条无用的且重复的commit
    • 有时候手滑不小心把不该提交的内容 commit 了,这时想改回来,只能再 commit 一次,又多一条“黑历史”。
    • 规范些的团队,一般对于 commit 的内容要求职责明确,颗粒度要细,便于后续出现问题排查。本来属于两块不同功能的修改,一起 commit 上去,这种就属于不规范。这次恰好又手滑了,一次性 commit 上去
  3. 使用方法:

    • git reset --soft DEAD
    • vscode使用

    vscode_commit.png vscode_commit_2.png

    • sourceTree使用

    sourceTree_soft.png

  4. 注意事项:

    • 仅对未推送到仓库的commit有作用,对于已经push到仓库的commit,可直接使用git reset --hard HRAD回到指定版本,修改并commit之后,由于版本回退后又进行本地修改,本地分支和远程分支会有差异,需要使用强推送push -f进行覆盖
    • 对未推送的commit使用git reset --soft命令回到某个版本后,该版本后的commit将被清楚,同时改动的代码都将回到暂存区
    • reset --soft 指定 commit 时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit

cherry-pick

  1. 命令作用:

    • 复制目标分支的commit信息及文件改动到新的功能分支
  2. 使用场景:

    • 有时候某个版本需求开发到一半的时候,可能其中某部分需求需要临时上或者提前上线,这时候就需要把完成的某个模块的commit抽出来,单独处理在新分支上开发上线(存在问题,几天一次的commit提交,就很难这样抽出,首先没遵守颗粒度提交,而是多个功能合在一个commit)

    • 有时候同个项目不同的需求不同的人同时进行开发的时候,可能由于两个功能版本不一,会存在部分功能需要交叉使用的情况(接口数据变化,原先部分代码会报错),但又不需要使用到对方全部功能时候(剩下功能在成熟开发至上线的时候在进行合并即可),在这样的情况,只需要复制对方促销活动主要模块的功能到自己分支上才能正常进行开发

    • 开发分支的代码记录被污染了,倒是开发分支合到线上分支有问题,这时候需要拉一条干净的分支,在从旧分支把无污染的commit复制到新分支(忽略被污染的提交,可减少拉整个分支出来,在一步步做污染剔除工作)

    • 有时候两个开发人员在进行同个项目不同需求的开发,A先开发,B后开发,但B开发的东西会需要依赖A需要上的一部分功能,这时候可以把需要的commit提交复制到B的开发分支上

  3. 使用方法:

    • git cherry-pick HEAD 复制目标commit应用到当前分支

      复制目标分支为 feat: 新建cherry-pick文件 的commit: cherry-pick.png

      需要开发的功能分支: 执行git cherry-pick 8fef452c88a0fa789a5aa98688b67bc660187f8d后,看下最新的log,该commit功能已应该到当前功能分支,且作为最新的commit还保留之前的提交信息,方便溯源 target_commit.png

    • git cherry-pick HEAD HEAD (复制多个) 一次复制多个commit

    • git cherry-pick HARD^..HARD 复制多个连续提交的commit

    • git cherry-pick --continue 继续进行下一步

    • git cherry-pick --abort 取消全部操作

    • git cherry-pick --quit 中断操作

      当复制多个时会有产生冲突情况,cherry-pick就会停下,让用户根据实际需要进行继续,中断或取消的操作

      假设我要复制目标分支的1,2,3的commit提交 cherrt-pick_list.png 在当前功能分支执行git cherry-pick HEAD^..HEAD复制多个的命令操作 cherry-pick-muilt.png 这个时候产生了代码冲突 cherry-pick_conflict.png

      当出现冲突时不要慌,vscode已经给出了提示,先去根据需要解决冲突,解决完毕后提交至暂存,在运行cherry-pick --continue继续进行下去,如若进行的下一个commit复制还有冲突则进行相同的操作便可 image.png

      如若不想继续后面的复制,运行git cherry-pick --quit 则可中断cherry-pick的操作

      如果发生代码冲突后,想放弃此次操作,运行git cherry-pick --abort,则可回到操作前的状态

  4. 注意事项:

    • 复制commit成功后,都将会产生一个新的提交,提交的commit哈希值和原来不同,但是标识名称一样,也可理解文件改动记录保持之前,如产生冲突的情况下,解决完冲突后,文件修改的记录将更新为自己

revert

  1. 命令作用:
    • 将现有的提交还原,并保持最新的修改,恢复提交的内容,并生成一条还原记录。
  2. 使用场景:
    • 手滑一不小心把不想要的代码,或是某次提交说明太愚蠢了,现在想要干掉它,commit到本地仓库中了,但是还没有做push操作!
    • 刚线上更新的代码出现问题了,需要回退到某次commit之前的代码,如果使用reset的话,最新更新的代码也将一并回退,致使后面有需要重新合并代码,无形之中提高了项目开发的风险,而这时候使用revert还原这次提交的代码!通过工具给出的差异提示重新进行修改commit所提交的功能,同时保留了最新功能,对于之前的commit记录可根据情况删除或修改
  3. 使用方法:
    • git revert HEAD

    • vscode使用

      image.png

      image.png

    • sourceTree使用

      image.png

rebase

rebase -i
  1. 命令作用:
    • p,pick 使用该提交,也是默认操作,这个从上面的编辑区域可以看出。这个命令的含义是拿到这个命令,但是什么都不做。

    • r,reword 拿到提交,修改提交的提交信息。

    • e,edit 拿到提交,修改这个提交的内容。使用这个命令的时候,rebase 操作会停在操作提交处,等待修改完毕,使用git add .git commit --amend修改提交,git rebase --continue继续 rebase 进程。

    • s,squash 这个命令很厉害的,可以将使用这个命令的提交与它的父提交融合为一个提交。

    • f,fixup 和 squash 命令的作用一样,不同的是,squash 命令会把融合的提交的提交信息都保存融合后的提交信息中,但是 fixup 会放弃被融合的提交。

    • d,drop 删除提交

    • x,exec 这个不常用,有兴趣可自行深入研究。

  2. 使用场景:
    • 合并当前分支多个commit记录,打磨commit颗粒度,可以保持一个清晰的提交历史,并让每个提交都有意义,有利于代码的长期维护
    • 修改提交说明,精炼commit信息
    • 修改提交的文件,可减少无意义的commit
    • 删除某个commit提交,连同提交的文件一同删除,避免重新删除在进行一次commit提交
  3. 使用方法:
    • git rebase -i [startpoint] [endpoint]

      合并从当前head到15f745b(commit id)
      git rebase -i 15f745b
      或:
      // 合并最近的两次提交
      git rebase -i HEAD~2
      
    • 合并commit ssquash

      目前有1,2,3,三个commit提交,需要将2合并至3 image.png

      运行git rebase -i HEAD~2命令后,控制台出现如下展示

      image.png

      合并操作是自上而下的,修改接收合并的commit状态,目前分支将会被合并进来

      image.png 保存退出则出现下一步,这时就可以修改提交的信息 image.png 这时就可以修改提交的信息 image.png 修改成功后在运行git log查看提交信息,2和3已经合并成功

      image.png

    • 使用提交,但修改提交说明 rreword

      假如修改3的提交信息

      image.png

      运行git rebase -i HEAE~1进入变更为编辑状态

      image.png 保存修改退出进行下一步编辑提交信息

      image.png

      保存修改退出后运行git log查看,此时3的提交信息已被修改

      image.png

    • 修改提交说明和提交内容 eedit

      假如修改3的提交说明和提交内容

      image.png 保存修改退后,出现如下操作步骤,修改进行还在进行中,这时可以去修改提交的内容文件,修改完后运行git add .将文件暂存,然后运行git rebase --amend进行修改提交说明

      image.png

      修改之后的commit历史

      image.png

      最后在运行git rebase -i continue进行下一步执行变基成功

      image.png

    • 删除提交 ddrop

      加入要删除最近一次的提交

      image.png

      运行git rebase -i HEAD~1进入变基编辑删除命令

      image.png

      保存后退出,运行git log 查看commit提交目标提交已被删除

      image.png

  4. 注意事项:
    • 使用rebase -i编辑操作后,普通推送到远端的话会提示与远程分支有差异,需要先拉取代码,但是一拉取话代码又会恢复操作前的样子,一切功夫就白费啦,所以进行rebase -i操作后,需要强推送至远程仓库
rebase branch
  1. 命令作用:

    • 合并分支,避免出现分叉合并,合并为线性历史,保持简洁的线性历史
  2. 使用场景:

    • 保持线性合并的历史分支情况下
  3. 使用方法:

    • git rebase branch

      运行git rebase xxx 将目标分支合并至主分支,

      然后发现有冲突的情况

      image.png

      这时就先根据需求解决分支啦,然后执行git add .将文件暂存(不需要运行 git commit),后执行git rebase --continue继续进行变基(若不想进行此次变基可以执行git rebase --abort放弃此次操作)

      image.png

      这里可做提交说明的修改,根据需要保存后退出即可,这时候如果使用git status查看,会告知你落后于自己远端分支,让你使用git pull合并远程分支,因为使用了变基,本地commit的哈希值已经被改变,和远程仓库的commit哈希值已经不匹配,故提示与远程仓库落后

      image.png

      此时解决的方法

      一是拉取代码,但是会产生冲突,需要根据合并情况解决冲突后提交至仓库便可

      二是直接使用强推送进行覆盖便可

  4. 注意事项(变颜色,划重点):

    • 永远不要在公共分支上使用rebase命令, 如果公共分支和你的分支不一样,这个时候对公共分支使用rebase合并分支的话,会出现你的分支落后于你的远程分支的提示,让你git pull合并,这个时候,无论你是git pull或者git pull --rebase,你都会获取到dev的分支杂乱的commit信息和杂乱的代码到你的分支。如果再合并到master上,就有一些乱七八糟的代码,从公共分支,进入你的分支,然后进入master分支

总结

  • 文中列举的应用场景有部分不太恰当,但是为了同学们便于理解,而最终的目的还是如前言所说,能够更加优雅的管理仓库代码和记录,提高项目开发过程中的容错率,也提升开发效率

  • 如果伙伴们发现问题欢迎指出