Git相关
一.Git的优点
1.相比SVN,Git更适合分布式模式,提交代码后并不仅仅上传到云端,本地也会有对应的版本库,这样在没有网络的时候也可以提交代码或者查看历史记录。
2.Git有本地库,可以在本地提交很多次,开发完成后可以一次push到版本库,而之前的提交不会影响到其他开发者。而且SVN的提交还需要提前做SVN up,每一次提交都可能面临冲突。
3.Git的分支和合并支持更好,分支其实就是一个指针,而SVN的分支却是一个新的目录,要切换分支就要切换目录,而Git只需要根据指针找到对应的commit对象,回复到该对象所指的文件快照即可。
4.Git比SVN更快,因为Git库就在本地,所以本地提交即可,而push的是一个压缩文件,而不是一个个文件都进行push操作。
二.Git的工作原理
1.记录整体快照。 Git以全部文件为单位记录差异,而大多数其它系统以一个文件为单位记录差异。
2.保持数据完整性。 保存到Git之前,所有的数据都需要校验计算,并将计算结果作为数据的唯一标识和索引。Git使用SHA-1算法计算数据和校验和,通过对文件的内容或目录的结构计算出一个SHA-1哈希值,将其作为指纹字符串。该字符串由40个十六进制字符组成。Git数据库中的东西都用此哈希值作索引,而不是文件名。
3.很多操作都只涉及增,而不涉及删改。 因为很多操作只是增加数据,所以Git的操作大多数都是可逆的,只要定期提交就不会丢失数据。
4.三种文件状态,modified、staged、committed。 modified:文件已修改,但还没有提交保存;staged:文件已暂存,修改后的文件已经放在了下次提交要保存的清单中;committed:文件已保存到本地数据库中了。
-
git目录。 .git目录,用来保存元数据和对象数据库。暂存区域其实就是个简单的文件,放在git目录下,该文件又名索引文件。
-
基本的Git工作流程。
- 在工作目录中修改某些文件。
- 对修改后的文件进行快照,保存到暂存区域。(git add)
- 提交更新,永久保存。(git commit)
- push到远程服务器。
三.Git客户端的常用操作步骤。
-
创建版本库的基本操作。
- 一般建议使用http或https协议,如果要使用ssh协议,需要先在个人资料添加ssh密钥。
- 配置用户名(username):git config --global user.name username。
- 配置邮箱(user@email):git config --global user.email user@email。(统一使用公司内部邮箱地址)
- 配置密码:git config --global credential.helper.store。
- 复制url。复制url,打开本地的git bash,执行git clone就可以下载。
- IDE扩展打开。可以用vscode扩展打开此链接,然后把项目代码下载到本地指定位置。
-
检查当前文件状态。 指令:git status。若显示nothing to commit, working tree clean则上次提交后所有的文件都未更改。
-
添加文件目录。
- 先用git status找到新创建的文件和目录,Untracked files后面就是新的文件和目录,都处于未跟踪状态。
- 使用git add xxx来跟踪一个新的xxx目录或文件。此时该文件或目录就处于暂存状态。
- 使用git commit -m xxx将暂存区中的内容提交至版本库,此时使用git status指令就可以发现working tree clean。
- 使用git push remote-name branch-name就可以将本机的工作成果推送到远程仓库,如果已指定过remote-name branch-name,则直接用git push即可。
-
重命名目录和文件名称。
- 使用git status指令发现重命名的本质就是删除旧目录和文件,添加新目录和文件的过程。
- 使用git add xxx将重命名提交到暂存区。
- 使用git commit -m xxx命令提交重命名。
- 同上git push。
-
修改文件内容。
- 修改文件后,使用git status检查文件状态。
- 使用git add 提交修改到缓存区。
- 使用git commit -m xxx提交到版本库。
- 同时git push。
-
更新文件或目录。
- 更新到gitlab上一致的目录文件中时,使用git fetch或者git pull指令。两者的异同是,都会从远程获取更新版本到本地,而只有后者会自动merge。
- 如果需要更新到一个特定的版本,就需要git log查看历史记录就可以找到对于版本对应的哈希值,然后git checkout hash_value既可以将对应的版本提取出来。(这里的哈希值就是前面根据SHA-1算法生成的唯一索引)。
- 更新后,当前的代码就是指定版本的代码。
- 此时可以commit到本地库,但是不是push到远程服务器,因为和远程服务器不在一个分支上。
- 可以使用git checkout main回到主分支的版本,此时就不需要对应的哈希值了。
-
删除目录或文件。
- 删除目录或文件先在本地删除,指令是git rm -r(-r如果是主目录名时就允许递归删除)。
- 然后commit push。
-
文件恢复。
- 如果只是修改了文件,没有其他git操作,git checkout即可回退。
- 如果修改了,也git add到暂存区了,则先git reset HEAD回退到当前版本,然后git checkout -- xxx。(xxx为文件名)。
- 修改了,也add了,也commit了。先git log --oneline查看历史记录,然后git reset HEAD^回退到上一个版本,最后git checkout -- xxx。
如果我们想恢复到某一版本,且该版本后面的版本都不要了,则使用git reset,如果该版本后面的版本需要留着,就是用git revert,该指令会记录整个版本的变动流程。
-
查看版本历史。
- git log 可查看历史所有版本信息。
- git log -x可以查看最新的x个版本信息。
- git log -x filename可以查看某个文件最新的x个版本信息(需要进入该文件所在目录才可以执行该指令)。
- git log -- pretty=oneline查看历史所有版本信息,这样查看只包含了版本号和记录描述。不会包括作者和日期。
-
过滤上传文件的类型。 先通过touch .gitignore指令生成.gitignore文件,再将需要忽略的文件类型加到.gitignore文件中,但是已经被追踪的文件是无法被忽略的,哪怕加到了.gitignore文件中。
四.分支管理
- 分支的优点。 自己可以随时更新保留进度,避免工作成果丢失,也不影响别人的工作进程,完成自己的工作后再合并到主分支即可。
- 分支是什么。 本质是指向commit对象的可变指针,main是分支的默认名字。 创建一个新的分支就是创建一个指针,使用git branch命令。在提交后,已经有一个指向commit对象的main指针了。每一次提交都是在当前指针下向前(后?)移动。
-
当前工作的分支。 HEAD指针指向的就是当前工作的分支,使用git log可查看。
-
切换分支时发生了什么。 本质就是移动了HEAD指针,使用git checkout branchName可以切换。
-
分支新建与合并。 git branch branchName和git checkout branchName可以通过git checkout -b branchName一个指令实现。再分支上新建分支作修改后,可以通过git merge newBranch将刚才的分支合并进来。(如果顺着一个分支可以到达另一个分支,在合并两个分之时,只会把指针右移,这就是快进fast forward)。此时被合并分支(newBranch)已经没用了,就可以删掉了。(如果在不同的分支都修改了一个文件的同一部分,就产生了冲突,git会进行合并操作但没有提交,会等你解决冲突。未解决冲突的文件都以unmerged状态列出,git会在对应的文件里加入标准的冲突解决标记。
-
分支策略。(基本原则)
- main分支只能用来发布新版本,平时不能在上面工作。
- 平时的开发工作都放在dev分支上,所以dev时不稳定的。测试通过后才能合并到main上,由main发布开发的新版本。
- 新需求、修复等具体任务,都应该在dev分支上开一个新的任务分支,完成后再合并到dev。
-
远程分支。 远程仓库中的分支,无法移动,只能在git进行网络交互时才会更新。远程分支的表示形式:远程仓库名/分支名。使用git remote -v查看远程仓库的情况。
-
跟踪远程分支。 从远程分支checkout出来的本地分支,称为跟踪分支。即跟远程分支由直接联系的本地分支就是跟踪分支。在跟踪分支里输入push,git会自动配对对应服务器的对应分支,也可以git pull获取所有远程索引,将远程数据合并到本地分支。克隆仓库时,git就会自动创建一个名为main的分支跟踪origin/main。这就是push和pull指令可以不加其他参数就可以执行的原因。
五.Git使用规范。
-
版本控制软件基本使用流程。
- 从主干远程仓库fork到自己的远程仓库。
- 从自己的远程仓库clone到本地计算机仓库。
- 修改文件添加新的代码然后commit。
- 修改文件添加新的代码然后commit。
- 从主干远程仓库拉取最新的代码。
- 合并第3、4步提交的内容。
- push到自己的远程仓库。
- 从自己的远程仓库发送合并请求到主干远程仓库。
-
分支管理策略。
-
主分支master。用于发布,面向用户的交付版本。与生产环境保持一致。
-
开发分支Develop。仅一个,用于项目第一轮集成测试,不允许直接合并到主分支,只是用来合并功能分支及自动构建测试包使用。与开发环境保持一致。
-
验收分支UAT。仅一个,用于第二轮集成测试,始终和UAT环境保持一致,通过测试验收后合并到master。
-
临时性分支。功能(feature)分支、(hotfix)修复分支。
-
功能分支。面向某种特定功能,从Develop分支上分出来的,后需要合并入Develop。
-
修复分支。软件发布后,出现bug,从Matser分支上分出来一个修补分支,来解决这个bug,然后再合并到Master和Develop分支。命名规范:hotfix-*。
-
环境:
- 开发环境: 开发过程中开发人员进行测试的服务器,为了测试方便,配置简介、变更频繁。
- 测试环境: (也用于Develop分支)测试人员进行测试的服务器,配置更正式,主要以白盒测试为主。
- 验收环境(UAT): 用于用户体验的服务器,与生产环境相同,但不连接数据库。
- 生产环境: 对外提供服务的服务器,不会开启错误报告,而是开启错误日志。
-
tag。对当期提交点的一个记录,tag的名字具有唯一性。tag的作用和branch类似,但是branch可以看成多个tag汇成的一根线(多次commit),有一个HEAD指针,可以根据指针移动,但是tag就是静态的一个点,一次特定的提交。所以需要改代码的时候就用branch,只查看就用tag。
-
-
commit message规范。 (写在readme里面)
-
模板:[scope]: [bug/story id]
-
type:
- fix:修复Bug。
- feat:新增功能。
- test:调试功能。
- style:变更代码格式或者注释。
- docs:变更文档。
- refactor:重构功能或方法。
-
scope:用于定义type的影响范围,数据层、控制层、视图层...
-
bug/story id:涉及到的禅道bug或者需求的编号。
-
subject:简短描述,少于60个字。
-
六.常见问题的解决方案。
如何让代码冲突变少? 开发前,将主仓库的分支上拉取最新代码,合并解决冲突。完成部分功能后,提交合并请求,将代码合并到主仓库分支中。提交合并到主仓库之前要先拉取主仓库分支代码合并带本地仓库。
一。查看代码仓库状态:git status
二。日志:
查看日志:git log
可以自定义日志的输出格式:git log --pretty=format:" xxxxx"(根据git文档找到对应的标识符)
查看最近n次的提交记录:git log -n
显示每次提交的差异:git log -p
查看被修改的文件以及修改操作:git log --stat
查询提交时说明里含有某string字符串的历史记录:git log --grep string
三。跟踪文件:
创建新文件:touch newFIle
查看并打印目录中所有文件名:ls
跟踪某个文件:git add new_file.cpp,跟踪后:
跟踪所有文件:git add . / git add * 前者会忽略.gitignore里面的文件类型,后者不会。
删除跟踪文件:git rm -f xxx。
删除跟踪文件,但在工作目录中保存:git re --cached xxx。
四。提交
提交:git commit -m "xxxx"。
跳过暂存区域提交:git commit -am "xxxx"
修改最近一次的commit备注:git commit --amend -m "xxxx"
回退到第一次提交的版本,重置暂存区和工作目录:git reset --hard HEAD^
五。分支
查看分支:git branch
重命名分支:git branch -m old_branch new_branch
创建分支:git branch new_branch
切换分支:git checkout new_branch
创建并切换到新分支:git checkout -b new_branch
缓存当前状态:git stash push
恢复到之前的状态:git stash pop
重命名暂存区文件:git mv oldxxx newxxx
六。标签
查看已有标签:git tag
为上一次提交打上一个标签:git tag v123
查看标签v123对应的提交:git show v123
\
转载自:https://juejin.cn/post/7031420578699427848