全文结构:
1)仓库概念
首先从总体上看,git的存储、操作:
主要涉及到四个关键点:
- 工作区(workspace):本地电脑存放项目文件的地方,比如learnGitProject文件夹;
- 暂存区(Index/Stage):在使用git管理项目文件的时候,其本地的项目文件会多出一个.git的文件夹,将这个.git文件夹称之为版本库。其中.git文件夹中包含了两个部分,一个是暂存区(Index或者Stage),顾名思义就是暂时存放文件的地方,通常使用add命令将工作区的文件添加到暂存区里;
- 本地仓库(Repository):.git文件夹里还包括git自动创建的master分支,并且将HEAD指针指向master分支。使用commit命令可以将暂存区中的文件添加到本地仓库中;
- 远程仓库(Remote):不是在本地仓库中,项目代码在远程git服务器上,比如项目放在github上,就是一个远程仓库,通常使用clone命令将远程仓库拷贝到本地仓库中,开发后推送到远程仓库中即可;
2)分支概念
1)分支介绍:
- develop 分支(唯一):用于平时开发的主分支,并一直存在,永远是功能 最新 最全的分支。
- feature分支(N个):用于开发新的功能的分支,一般是多个员工一人一个feature远程分支。
- release分支:用于发布准备的专门分支。
- master 分支(唯一):最为稳定、随时可发布的代码;所有在 master 上的提交都必要要有 tag ,方便回滚。
- hotfix分支:用于修复线上代码的 bug
2)分支关系:
develop和master是2个主要分支,这两个都是唯一的;
其他的3种分支都是从这2个分支派生出来的:
feature从develop拉出,并回到develop
release从develop拉出,并推送到develop+master两个分支(保证同步)
hotfix从master拉出,并推送到develop+master两个分支(保证同步)
3)特性总结:
生命周期:
feature和hotfix是临时的
其他3个都是长期存在
直接开发:
从不:master、release
不建议:develop
直接:feature、hotfix(和临时对应)
一、基础流程
首次需:
0. git init 初始化新仓库(init 好像没啥用)
1. 到代码文件夹,右击 Git Bash Here,打开到本文件路径
2. git clone + GitHub网页上Repository复制下来的 URL
3. 此时是远程分支是origin/master(origin层次下的master分支);本地分支是默认的master;需要切换远程分支和本地分支:
git checkout -b jqy-local-dev(本地分支名)origin/dev(远程分支名)
(如果没有这一步的操作,就会从master拉取,因为SSH的url只有一个)
3.1先用 git branch -a 查看所有本地+远程分支
3.2 切换分支
注意上图中本地分支已经切换,origin/dev是根据需要选择的远程分支,远程分支改变后,本地文件会由origin/master这个远程分支变为你选择的远程分支
(ps: 将本地分支和远程分支关联的操作一般只用于拉取的时候,而后面就不用管这个关联了,因为git push origin jqy 这个指令一般不用,都不会原路推到代码来源如dev远程分支,而是push到自己的远程分支,然后MR等待评审再合并到需要的分支)
后续:
不断编码修改...
4. cd到新文件夹中,Git Bash
5. git add . (注意" . "不能省略,此操作是把文件夹下面新的文件或修改过的文件添加进来,如果有的文件之前已经添加了,它会自动省略)
6. git commit -m "提交信息" (提交的信息是你的项目说明)
7.(配置好用户名、邮箱)
8. git push origin master
git push [remote-name] [branch-name]
(此操作目的是把本地仓库push到github上面,此步骤需要你输入登录github上的帐号和密码)
(一般团队开发都用 git push origin jqy:jqy001这样推到自己的远程分支,然后提交MR;而不是直接push就完事)
git push origin jqy:jqy001 本地分支提交到远程分支
(9.) 如果push的时候显示冲突(有人改了对应的远程分支),就先pull一下:
git pull origin jqy001
对比冲突,解决后再push
10. 然后在网页中Submit MR,比如从jqy001==>dev
等待代码审核即可...
二、分支管理
git branch 查看本地分支;
git branch -a 查看所有分支(包括远程)
上方是本地分支区,下方origin一堆是远程分支;箭头指向的是当前本地分支、远程分支
git checkout -b [branchname] 创建+切换 分支
- git branch dev 创建分支(这个一般用不上)
- git checkout dev 切换分支(此处的dev可以为git reflog的七位数字)
git branch -d [local-branch-name] 删除分支(本地)
git branch -r -d [remote-branch-name] 删除(远程remote)分支
修复上一个版本的bug:
1. git log找到bug版本的版本号
2.git branch 1db3731将HEAD移动到bug版本
3.git branch -b myfixbug然后开始在此分支修改bug
4.等到master里面到下一个版本上线之前,合并myfixbug
最好看着IDEA中的版本线状图===》》》
顺便学习Github/CodeHub团队开发策略(分支策略)总结下来
- git push origin master //push到origin的master分支
- git push origin dev //push到origin的dev分支
git remote -v 查看连接SSH的url (远程库的默认名称是origin)
git branch -v
git branch -vv
显示local分支对应的远程分支
设置origin:
三、团队开发 - MR提交
在团队合作软件开发方面,一般有master分支和develop分支,
开发者先发送merge request请求到develop上,然后通过 项目管理者review之后,才会merge到master分支上。
Merge Request
(建议在IDEA里面进行,因为方便对照修改的内容):
git branch -b jqy 建自己的本地分支
git add 需要修改的文件(最好不要用git add . 因为这样会add上一些无用的东西)
git commit (提交到自己的本地)
git pull origin jqy001 (与origin中jqy001这个远程分支进行对比,修复冲突,并提交需要上线的文件)
git push origin jqy:jqy001 本地分支提交到远程分支
成功的话,然后在网页中Submit MR
(然后就会由管理员审核MR并提交UAT测试环境。。)
Merge Request(这种方法一般在push的时候会被卡主)
1) git checkout -b xxx (xxx是新建分支的名字,如feature_i)
2) git add . git commit -m "..." git push origin xxx //在自己的xxx分支的操作
3.1) git checkout master git merge xxx git push origin master //切换到master进行合并【命令行版】
3.2) (一定确保第2步有git push origin xxx)然后在gitlab界面进行merge request的信息填写 【GUI版,适用于代码审核】
四、解决冲突
git merge dev // 一般将dev分支的修改merge到master分支上
merge的时候,如果有同时修改的内容, 就发生冲突(此时无法自动merge),需要查看conflict然后手动合并。
一开始两个不同的分支同时修改master的readme文件:
第一个merge的不会出问题,
第二个merge时候:
在 git merge feature_1之后,查看feature_1的文件,会显示比对信息:
手动修改readme文件(不用切换到feature_1分支),
然后在master分支上面,add+commit
然后直接 git push origin master就好了(可以在gitlab 网页GUI上面直接看一下验证):
【另一种方式push】
第二个push出现冲突时:
然后git pull
修改、git add、git commit
然后再push就好
五、回退版本(时光穿梭机)
git status 查看工作目录、暂存区的状态
git diff 查看修改内容 (Git跟踪并管理的是文件的修改,而非文件本身)
git diff 详细命令: https://www.jianshu.com/p/80542dc3164e
git log 查看日志(一次次commit修改情况,注意是以commit为粒度)
(git log -p 可看到具体修改内容。按Enter向下阅读)
1)已经commit之后
- git reset --hard HEAD~1 回退1个提交(彻底回退,冲掉回退的信息)
- git reset --soft HEAD~1 回退1个提交+保留代码修改信息
- git reset --hard d311cd2 ==》先用git reflog 查看各个版本的 commit id(如d311cd2)进行自由回退 (很好用!)
2)已经add,但没有commit(错误还在 stage暂存区)
两步操作:
git reset HEAD [filename]
git checkout -- [filename]
3)还没有add(错误还在 工作区)
只需要一步:
git checkout -- [filename]
(这样操作的粒度比较小;reset的话,粒度比较大;因为一般是一次commit是一到多次add的总和)
分析下粒度:
多次add,一次commit;
多次commit,一次push;
所以:
commit后的reset --hard 序号《==》1~n次的commit的粒度
add后的reset HEAD《==》回退到上次commit后的状态,相当于1~n次的add的粒度
add前的 checkout -- [filename] 《==》回退到上次add后的状态,相当于1次add内的粒度
详细说明git reset:
git reset --hard HEAD^ 硬回退一步
(此时本地回退了,但是远程没有回退;如果需要远程也回退,就要git push origin xxx再提交一下)
git reflog 查看各个版本的 commit id(如d311cd2)
git reset --hard d311cd2 根据后面的commit -m "..."信息,找到对应的id,进行自由回退 (很好用!)
六、忽略文件 .gitignore
1)规则
/ //表示目录 * //匹配 任意个字符 ? //匹配 一个字符 [ ] // 正则匹配 一个字符 ! //表示忽略匹配
2)示例
# 此为注释 – 将被 Git 忽略 *.log #表示所有的 .log文件(也包括子目录里的) *.iml *.ipr *.iws *.txt # 忽略所有 .txt 结尾的文件 !Readme.txt # 但 Readme.txt 除外 /TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO /node_modules hello[0-9].txt .settings/ # 忽略settings文件里的全部 .idea/ .vscode/ target/ .gradle /config build/ # 忽略 build/ 目录下的所有文件 doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt /fd1/* #忽略根目录下的 /fd1/ 目录的全部内容; fd1/* #忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
想把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
git rm -r --cached .
git add .
git commit -m 'update .gitignore'
PS:理解CRLF / LF
- CRLF 回车换行。 Windows 换行方式 CRLF== carriage return line feed
- LF 换行。 Linux&Unix 换行方式 LF== line feed
两个字符,只删除
是不够的。所以在读取文件的时候一定要小心跨平台。Git 提供了一个名为
core.autocrlf
的配置,可以自动完成标准化与转换。它的设置方式如下:git config --global core.autocrlf [true | input | false] # 全局设置
git config --local core.autocrlf [true | input | false] # 针对本项目设置
- true:CRLF <=> LF
- input:CRLF => LF
- false:不变
注意:
- CRLF 与 LF 混合的文本文件不受此配置控制。
- Git 安装后默认为 false
使用 Windows 系统的开发者设置:
git config --global core.autocrlf true
使用 Linux/MacOS 的开发者设置:
git config --global core.autocrlf input
ps:IDEA界面化Git操作
更多内容参见:《Git -- IDEA界面操作》
命令行操作是git的根基,在此基础上的 IDEA界面操作,功能更加可视化、易于理解。
参考 git使用教程(有详细实例): https://zhuanlan.zhihu.com/p/30044692
git基本操作(精简手册):https://juejin.im/post/6844903598522908686