在开始写笔记前,我还是想简单说一下我的 git 学习路线,希望能帮助到有缘人。
首先当然是看 git 命令教程,当时看的廖雪峰的 git 教程
其实教程看完之后,虽然对命令了解了,但是直接往项目里用还是很发怵的。。所以这时候开始用 git 图形界面了,用的 SourceTree,挺不错的一款可视化界面。
用了一段时间 SourceTree 后,之前学的 git 命令忘得差不多了,但是这时候对仓库代码的管理思路却是异常的清晰。再回顾一下之前刚学完 git 命令的时候,能感到明显的差异,之前是命令都知道,但是面对代码下不去手,不知道该用什么命令做什么操作;而现在是面对代码知道该干什么了,但是要用命令的话还需要再翻翻教程。
到这个状态之后,我觉得是时候再次尝试用命令操作 git 的时候了,所以就有了这篇记录。回顾这整个学习使用过程,其实还挺奇妙,饶了一大圈最终还是回到起步的地方,就像 android 源码调用栈,哈哈~
这里先交代一下我们的仓库背景。在我们项目中,主要用到的就是两个分支 master
和 feature
。
master
这是我们项目的主分支,它有一个相对应的远程仓库的分支 origin/master
。在这个分支里不进行新功能的开发、修改 bug 等操作。它的作用就是使各开发人员的本地仓库保持统一。
feature
这个分支是本地分支,它在远程仓库没有对应的分支,其实这个本地开发分支名字随意起,怎么高兴怎么来,因为它只属于当前开发人员一人。平时的开发、修改 bug 等操作,在这个分支去进行,任务完成后把它合并到 master 分支并推送到远程 master 分支,始终保持 master 分支是稳定可靠的最新代码。
这个场景记录,差不多可以概括为我工作的一天了,从早到晚,打完收工。
我想大家开始写代码前第一件事应该跟我差不多吧:先切换分支到 master
分支,然后从远程仓库拉取一下昨天同事提交的最新代码;然后切换到本地开发分支 feature
,把 master
分支的最新代码合并到自己的开发分支 feature
,接下来就可以开始自己的模块开发了。
对应的 git 命令:
先切换分支到 master
分支
从远程仓库拉取最新代码到 master
分支
这里直接用 git pull
命令
可以看到,我从远程仓库拉取代码成功了,因为我截图之前拉取了一次,所以本地 master
分支的代码已经是最新的了,所以并没有什么文件的变动,这里就假装有文件变动吧。
切换到 feature
分支并合并最新代码
现在我本地的 master
分支已经是最新代码了并且跟 origin/master
分支保持一致,但是我的开发分支 feature
还不是最新的代码,且看下边操作:
一顿操作结束后,这是我的 feature
分支的代码现在和 远程仓库 master
分支保持一致了,是最新的代码,可以开始我的开发工作了。
新功能太复杂一次可能写不完,我把它分成了两个小功能,现在我把第一个小功能完成了,在开始写第二个小功能前,我想提交以下代码做个记录,以防做第二个功能的时候需要重构然后把第一个小功能的代码也弄混了。
那现在就开始吧,当我第一个小功能做好的时候,我还没提交过代码,所以我改动的代码现在都在工作区,我要先把我改动的代码添加到暂存区,然后提交到我的本地分支 feature
。
这里为什么不继续合并到 master 然后推送到远程 master 呢?因为我之前说过,始终保持 master 分支是稳定可靠的最新代码,所以这里等我整个新功能开发完,然后测试没bug后,再推到 master。
对应的 git 操作:
把工作区的改动添加到暂存区
git 命令:
git add <文件名>
单独添加一个改动的文件到暂存区
git add .
添加所有工作区文件到暂存区
先看了下状态:在 feature
分支,工作区有个修改了的文件 build.gradle;添加到暂存区;再看了下状态,改动过的文件 build.gradle 已经被添加到暂存区了。
提交本次代码到 feature
git 命令:git commit -m "feat : a little new function"
可以看到我提交了一次代码并且成功了;之后查看状态,工作区和暂存区已经没有改动的文件了(已经提交了);查看提交日志,有我刚才的提交记录。
整个新功能都开发完了,并且测了一下没 bug,这时就需要提交代码后推送到远程仓库了,具体该怎么操作呢?
我当前是在 feature
分支,首先我得把工作区改动的文件添加到暂存区;然后把暂存区的文件提交到 feature
分支;这时新功能的代码已经在 feature
分支里了,我现在需要把它合并到 master
分支,所以我需要先切换到 master
分支,然后把 origin/master
远程代码拉下来(如果同事在我上次拉取后有提交了代码,我的本地 master
就不是最新的了,所以先更新一下本地 master
);然后把我本地 feature
分支合并到 master
分支;接着把合并好的 master
分支推送到远端。
对应的 git 操作:
把工作区的改动添加到暂存区
和上一个场景的操作一致,不介绍了直接放图
提交本次代码到 feature
切换分支到 master
并拉取远程仓库最新代码
把我本地 feature
分支合并到 master
分支
用到的 git 命令:git merge feature
可以看到合并操作成功了;查看状态本地 master
分支比远程 master
超前一个版本。
把合并好的 master
分支推送到远端
用到的 git 命令:git push origin master:master
到这里,我开发的新功能就推送到主分支了,其他同事再从远端仓库拉取代码就包含我写的新功能了。
日常开发工作中的使用 git 场景基本上就是这了,其实最主要的还是思路,思路清晰用起 git 来就会得心应手了,就算命令记不清了,但是知道下一步该干什么。简单查查就能接着搞。要是没有思路就麻烦了,总觉得一个操作就会毁了仓库一样,哈哈~
写到这里肯定是结束不了的,有常用场景下的 git 使用,必然就存在刁钻场景下的代码管理了。
我先描述一个场景,有这么一天,这天我正在 feature
分支写新功能,写了半拉子还没有提交。这时神秘人物突然反馈了个线上版本的紧急 bug 给我,限时 1 小时写完。惊喜意外之余,让我们来分析分析该咋办:
我如果要改 bug,就需要从当前的 feature
分支切换到 master
分支,然后从 master
创建新分支 bug
去改这个 bug。
那么问题来了,我现在在 feature
分支的修改是个半拉子,我不想把这个半成品提交到仓库,但是我还要从 feature
分支切换到 master
分支,同时不把这半拉子新功能的代码带到 master
分支,这该咋操作?
这里就要用到贮藏功能了,它的作用就是可以把当前工作区和暂存区未提交的修改暂时保存起来,清空工作区和暂存区,然后在需要恢复的时候可以把之前未提交的修改再恢复出来。
相关 git 命令:
git stash list
--查看当前的贮藏列表
git stash save
--保存当前工作区和暂存区的修改到贮藏列表,
是这个贮藏的描述
git stash apply
--恢复某个贮藏到工作区和暂存区
git stash drop
--删除某个贮藏
git stash pop
--恢复某个贮藏到工作区和暂存区,同时删除该贮藏
下面接着回到场景里:
我现在要先贮藏一下我的半拉子代码
可以看到我现在有一个文件修改了;执行贮藏操作;再看状态工作区和暂存区都干净了;然后看贮藏列表,有我刚才贮藏的代码。
这里修改 bug 的 git 操作全部省略,现在我改好 bug 了,并且 feature 也合并了 master 改好 bug 的代码了。接下来恢复贮藏接着我的新功能开发
然后就可以接着半拉子代码继续开发新功能了。
场景描述:某一天,我正在写新功能,然后新功能刚写完,我把代码提交到 feature
了,然后突然想再测一下,结果自测出了个 bug,就顺手把 bug 改了。这时要是直接提交,别人不就知道我写的新功能有 bug 了吗?不行,这样不妥,得想想怎么把刚才提交的新功能的代码悄无声息的退回来,和改 bug 的代码混合起来一起提交,刚好我 feature
分支的代码还没合并到 master
更没推送到远端,这样不就没人知道了,哈哈哈~
要想实现这个效果,就得来了解一下 git reset
这个命令了。
用到的 git 命令:git reset --mixed
--重置当前分支到
这个提交,它之后的提交的代码改动会存放到工作区并与工作区原有的改动混合
回到场景里开始操作:
先看一下 git 分支树
我们要退回到红框圈着的那次提交,它之后的那两次提交的代码改动会存放到暂存区
开始重置当前分支到某次提交
先看下状态,工作区和暂存区是干净的;重置分支到某次提交;再看状态,重置后后边的两次提交改动到工作区了;看 git 分支树,重置提交成功了。
把工作区和暂存区的改动重新提交,就悄无声息的把 bug 改了,具体操作就不写了,是常规操作前边写过了
其实还有几个经常用到的场景没有在上边体现出来,这里再记录一下。
场景描述:当你在做一个新功能时,写到某个程度后不管再怎么灵光一闪,就是差一点就完成开发。你静下心来想了想,突然恍然大悟,你从一开始的思路方向就错了。这时你需要回到起点换个思路重新开始撸这个功能。
假设你现在仓库的暂存区有已经暂存的修改
、工作区也有修改的文件记录
,你需要把暂存区和工作区的所有改动都清空掉,才能重新开始写功能。大致思路是这样的:先把暂存区的改动记录取消暂存恢复到工作区;然后把工作区的文件改动全部丢弃掉
下面来看 git 操作:
首先看一下现在的状态
可以看到,我现在暂存区有文件 build.gradle
的改动,工作区有文件 app/channel
的改动。
把暂存区的改动记录取消暂存恢复到工作区
用到的 git 命令:
git reset head <文件名>
--从暂存区取消暂存某个文件的修改
git reset head .
--取消暂存区所有文件修改的暂存
可以看到,现在已经把暂存区的文件改动取消暂存恢复到工作区了,接下来就是丢弃工作区的文件改动了。
把工作区的文件改动全部丢弃掉
用到的 git 命令:
git checkout -- <文件名>
--从工作区丢弃某个文件的改动
git checkout -- .
--丢弃工作区全部文件的改动
先看一下状态,改动都在工作区了;丢弃工作区全部改动;再看一下状态丢弃成功了。
以上就是丢弃未提交的改动的全部操作了,可能有的道友说他已经提交一部分到本地分支了,现在想把提交的也丢弃掉而且不再产生提交记录。其实这也很简单,先执行场景五 重置当前分支到某次提交,然后再执行场景六 丢弃没有提交的代码改动
。
场景描述:这个需求好像随时都会有,当你用 git status
命令时,你只看到了工作区和暂存区的文件的改动,那如果你想看文件内部都改动了哪行代码呢?这时候,这个场景就出现了。。。
用到的 git 命令:
git diff
--查看全部工作区文件内部的改动(与暂存区进行比较,暂存区如果没有,就是与当前分支最新的已提交的代码比较)
git diff --cached
--查看全部暂存区文件内部的改动(与当前分支最新的已提交的代码比较)
看状态,暂存区和工作区都有文件改动;查看工作区文件的改动(与暂存区比较);查看暂存区文件的改动(与当前分支最后一次提交后代码库比较)。
场景描述:我把新功能改完了,老板让打包正式版要准备发版上线了,我打包前要记录一下这个版本的仓库代码,而 Tag 标签就是个很好的方式,而且可能用过 CI 自动编译自动打包的开发者都知道,利用 Tag 标签还可以直接自动打包相应的版本。
操作思路:切换到 master
主分支;从远端拉取 tag (git pull);查看 tag 列表;根据列表创建一个新的 tag,推送 tag 到远端。
用到的 git 命令:
git tag -l
--查看 tag 列表
git tag -a
--创建标签
git tag -d
--删除指定标签(本地仓库)
git push origin
--分享标签到远程仓库
从远程拉取;查看标签列表
可以看到我的标签列表还是空的。那我要创建的标签就定为 1.0.0
好了。
创建一个新的 tag
我创建了一个新标签 1.0.0
;查看标签列表已经可以看到了
推送 tag 到远端
可以看到我已经推送成功了。
这些就是我日常工作中用的最多的几个命令了,基本可以应付工作中的代码管理,刁钻的问题也能解决,再遇到其他刁钻问题就再更新文章好了。
学习和使用 git 到现在,虽然还没到精通的水准,但是感悟还是挺深刻的,真的是最主要的还是思路一定要清晰。很感谢 SourceTree 这个可视化 git 客户端,让我忘掉命令的同时,对代码管理的思路更清晰了,等有思路后,再用回 git 命令就有一种得心应手的感觉了。
总结一下,就是刚开始学习 git,先把 命令学一遍;然后用 git 可视化客户端,忘掉命令理清代码管理思路;最后换回用 git 命令管理代码,有思路加持,一点都不怂~