Git
全文目录
前言
需要有git基础,了解基本的命令.因为一些问题需要解决所以才看这篇文档,参考了git的官方的一些描述和图片
这篇博客然后对日常开发问题做了一些汇总整理
官网地址
全篇符号
[] -> 释义,不参与git命令使用
<> -> 内容, 对内容的解释,使用在git命令当中
*① -> 特殊注释,在文底
() -> 解释
图形化理解git机制->HEAD指针
HEAD 是当前分支引用的指针
举例: 现在有两个分支,一个master分支 一个testing分支,现在HEAD指向master分支
![HEAD 指向当前所在的分支。](https://i-blog.csdnimg.cn/blog_migrate/f4748c86909e97ca4c1be40f394eedfd.png)
git checkout testing -> 切换分支到testing分支,此时HEAD指针指向了testing分支
![HEAD 指向当前所在的分支。](https://i-blog.csdnimg.cn/blog_migrate/318bad387cd68f494278c240137dc590.png)
如果我们在testing分支提交了一次版本,那么指针会指向testing分支的新版本,而master仍然停留在原处
![HEAD 分支随着提交操作自动向前移动。](https://i-blog.csdnimg.cn/blog_migrate/dfd829c7f9ab1508feea71504d89ca84.png)
如果切回master,会看到版本树变化,做了两件事,一是使 HEAD 指回
master
分支,二是将工作目录恢复成master
分支所指向的快照内容。 也就是说,你现在做修改的话,项目将始于一个较旧的版本。 本质上来讲,这就是忽略testing
分支所做的修改,以便于向另一个方向进行开发
![检出时 HEAD 随之移动。](https://i-blog.csdnimg.cn/blog_migrate/6fb57b8d99458bfccee07cdac0ab76df.png)
如果此时在master提交,那么从
f30ab
将会分叉
![项目分叉历史。](https://i-blog.csdnimg.cn/blog_migrate/815bdf9614775ec87f5c5abaf678cbf6.png)
基本命令
1. git add 提交到暂存区
2. git commit <message> 提交到本地仓库
3. git checkout <分支名> 切换分支
4. git push 拉取代码
5. git pull 推送代码
6. git status 查看状态
7. git log 查看日志
日常开发会出现的问题
1. 漏提交文件/信息写错
这种场景下,通常的补救措施就是重新提交一次,进行一次补充描述,但是对于版本日志来说,十分不友好.
场景: commit本次操作后,发现有几个文件漏提交了,或者提交信息写错了可以使用下面命令
git commit --amend[修改/修订]
又分为两种情况:
1. 提交完漏掉文件提交, 这时候执行add操作,再使用--amend命令第二次会覆盖掉第一次的提交
2. 提交完后,发现自己写错commit信息了,且add操作无数据,即暂存区无数据,执行--amend命令只会覆盖message部分
实质: 当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 新的提交替换旧的提交,从结果上看,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。
2. 已提交误操作
在Git中任何"已提交"的东西几乎总是可以恢复的.甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复.但是,任何你未提交的东西丢失后很可能再也找不到了
这种情况又分为三种 ,
- 已经add操作,提交到暂存区
- 已经commit 提交到本地仓库
- 提交了文件,但是这个文件的修改不想使用
*① add情况
git reset HEAD <文件名> 取消暂存对应文件名的文件,即对对应文件撤销add操作
*②commit情况
git reset --mixed(默认,可不写) HEAD^ 撤销本次commit,撤销add操作,本地改动的代码保留
git reset --soft HEAD^ 撤销本次commit,不撤销add操作,本地改动的代码也会保留
git reset --hard HEAD^ 撤销本次commit,删除本地暂存区(add)及commit改动的代码,**本地改动的代码也会删除**
HEAD^代表上一个版本 也可以写成git reset --<命令> HEAD~<n> 前几次提交
*③ 撤销对文件的修改
git checkout -- <文件名> 撤销本地包括提交的对该文件的所有修改,即放弃工作目录中的更改
3. 合并代码时发现本地代码丢失
分为2种情况
- 是git自动管理将你的代码存放在了stage中(基本上都是这种)
- 是极端情况下,怎么找都没有,最后一丝希望
第一种情况,一般是合并代码的时候,发生冲突,选择将远端代码覆盖了本地,本地的代码也并未commit提交到仓库
git会自动将你的本地冲突代码放到stage中,这时候也只需要存unstage中找到本地的记录,释放出来即可
处于第二种和第一种解决方案中间,idea本身有一个Local History 功能,会存储你本地对文件的所有更改,只要你没有清理idea Invlidate Caches ,本地的代码都能看到 可以选择批量回退,也可以根据单个文件回退,十分实用.
第二种极端情况什么地方都没找到,比如,合并的时候提交了代码后发现自己的代码更改不见了,stage中也不存在,或者reset误操作了.**(add过的文件都会在这儿)**
两种方案:
1. 通过命令 git reflog 查询commit前操作找到head指针位置 .再 使用 git reset --hard HEAD@{n}恢复
2. 或者直接去我们项目所在路径的.git文件下(一般是隐藏的需要开启显示隐藏文件夹)objects文件夹下,add过的文件都会在这儿,找到最近的版本,里面有一串乱码,打开就会发现是我们修改过的文件
4. 开发共同修改同一个文件,但并不需要提交
这种情况,比如说配置文件,每个人因为某些原因对本地的dev配置做了调整,但是并不需求提交.
方案一 加入忽略文件
.gitingore文件中添加对应文件,相对应的.gitingore也会提交.但是大家都不会提交这个文件了
方案二 交互式暂存git stash
每次合并代码前,将自己的文件存入stage区中,合并完成代码后,将代码unstash出来即可
方案选择的话,需要根据情况来区分,一般来说还是使用方案二好,有些文件最终还是需要提交一个版本,要是给漏掉了,会出现不少问题
5.将一个commit提交到另外一个非当前分支
这种情况,在错误的分支上进行了开发,想把错误分支上已经提交的代码重新在正确的分支上进行提交
1. 找到当前提交的commit分支的commitId
git log
2. 切到需要提交的正确的分支
git checkout <分支>
3. 在新分支上执行提交commit
git cherry-pick <commitIds>
以上即可将本地仓库的commit提交到另外一个分支,此时commitIds可以是多个
如果是多个使用 A B
如果是一个范围使用 A..B(不包含A)
如果想包含A 则 A^..B
标签tag
概念: tag 是一个标记,相当于指向某个commit 的指针 ,给分支做一个标记,打上一个版本号.tag 对应的是一个点可以称为快照 , 而branch分支对应的是一条线
作用: 看怎么想象去使用, 比如: 已经发布了v1.0 v2.0 v.3.0 版本,有一个新需求想在v2.0上增加新功能.即 v4.0 可以检出v2.0 代码做一个单独的新分支 ,作为开发分支.也比如说修改一个指定tag的bug,最后合并到现行的代码中
标签: 给commitId 版本做个标记,方便后面回退版本 (只会存在于本地)
1. git tag -> 查看当前所有的标签
2. git tag <name> <commitId> -> 打上标签
- name 标签名
- commitId 历史版本commitId , 通过git log 查询, 可不填,不填即为当前版本
3. git push origin <name> -> 推送本地标签到远程上
4. git push origin --tags -> 推送所有本地标签
5. git tag -d <name> -> 删除指定名称标签(本地)
6. git push origin --delete tag <name>(远端)
7. git reset --hard <tag>
git 日志
git log <命令> <参数>
序号 | 命令 | 作用 | 备注 |
---|---|---|---|
① | - n | 查找出最近提交的top n 命令 | 数字 |
② | –since / --after | 指定时间之后的提交 | 日期格式 |
③ | –until / --before | 指定时间之前的提交 | 同上 |
④ | –author | 指定作者的提交 | 支持模糊查询 |
⑤ | –committer | 指定提交者的提交 | 支持模糊查询 |
⑥ | –reverse | 按照时间倒序排列提交 | 最初->至今 |
⑦ | –HEAD --grep | 按照指定头部信息进行过滤 | 涉及到message规范 |
等等
Git 规范(AngularJS的开发指南)
格式: message分为三部分
Header(必须) Body(可省略) Footer(可省略)
构成:
<type>: <subject>
//空一行
<Body>
//空一行
<footer>
释义: type -> 说明commit类别,如:
feat: 新功能
fix: 修改bug
docs: 修改文档
style: 格式化代码结构(不影响代码运行)
perf: 性能优化
refactor: 重构(即不是新增功能,也不是修改bug的代码变动,比如重命名变量)
chore: 构建过程或辅助工具的变动(不会影响代码运行)
revert: 如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit的Header
例如: revert: feat: add 'graphiteWidth'
subject -> subject是 commit 目的的简短描述,不超过50个字符。
body -> 对标题的补充,但它不是必须的。和标题一样,它也要求使用祈使句且现在时态,正文应该包含更详细的信息,如代码修改的动机,与修改前的代码对比等
footer -> 任何Breaking Changes(破坏性变更,不向下兼容)都应该在页脚中进行说明,它经常也用来引用本次提交解决的GitHub Issue。
作用:
1. 基本上commit都只占用一行,很方便就能过滤出所需要的的功能
2. 统一了提交规范,能提高团队协作能力和自我的规范.
3. 方便生成change log 易观看
4. 代码提交在应该提交的分支,随时可以切换到线上稳定版本代码,多个版本的开发工作同时进行,提交记录的可读性
等等
CHANGE LOG
npm install -g conventional-changelog
$ cd <项目地址>
$ conventional-changelog -p angular -i CHANGELOG.md -w
上面命令不会覆盖以前的 Change log,只会在CHANGELOG.md的头部加上自从上次发布以来的变动。如果你想生成所有发布的 Change log,要改为运行下面的命令。
conventional-changelog -p angular -i CHANGELOG.md -w -r 0
注意事项
① reset 命令很危险,不了解的情况,可能会出现误操作,不要随意使用
② 一定要根据自己的需求去选择合适的代码,虽然hard的代码本地可能也会有记录
③ checkout 也很危险,因为会把你所有的修改都重置了, 没了,使用的时候需要注意情况