是什么
文件存储仓库
组成
- 工作区 (必要)
- 暂存区 (必要)
- 本地仓库 (必要)
- 远端仓库 (非必要)
- 储藏库(非必要)
目录关系图
graph LR
A[个人计算机]-->B[工作区]
B[工作区]-->C[.git(本地仓库)]
B[工作区]-->D[.gitignore]
B[工作区]-->E[其他文件]
C[.git(本地仓库)]-->F[HEAD]
C[.git(本地仓库)]-->G[config]
C[.git(本地仓库)]-->H[logs]
C[.git(本地仓库)]-->I[COMMIT]
C[.git(本地仓库)]-->J[index(暂存区)]
C[.git(本地仓库)]-->K[refs]
K[refs]-->L[remotes]
K[refs]-->M[stash]
K[refs]-->N[tags]
仓库关系
graph LR
A[工作区]
AC[修改后的工作区]
B[暂存区]
C[本地仓库]
A-->|change|AC
AC-->|add filename|B
B-->|commit|C
C-->|reset --soft commit_id|B
B-->|reset HEAD filename|AC
AC-->|checkout filename|A
C-->|reset commit_id|AC
C-->|reset --hard commit_id|A
B-->|reset commit --hard id|A
场景一:工作区与工作区修改
graph LR
A[工作区]
AC[修改后的工作区]
A-->|change|AC
AC-->|checkout filename|A
场景二:工作区修改与暂存
graph LR
AC[修改后的工作区]
B[暂存区]
AC-->|add filename|B
B-->|reset HEAD filename|AC
场景三: 暂存区与工作区
graph LR
A[工作区]
AC[修改后的工作区]
B[暂存区]
A-->|change|AC
AC-->|add filename|B
B-->|reset --hard HEAD|A
场景四: 暂存区与本地仓库
graph LR
B[暂存区]
C[本地仓库]
B-->|commit|C
C-->|reset --soft commit_id|B
场景五: 本地仓库与工作区修改
graph LR
AC[修改后的工作区]
B[暂存区]
C[本地仓库]
AC-->|add filename|B
B-->|commit|C
C-->|reset --mixed commit_id|AC
场景六: 本地仓库与工作区
graph LR
A[工作区]
AC[修改后的工作区]
B[暂存区]
C[本地仓库]
A-->|change|AC
AC-->|add filename|B
B-->|commit|C
C-->|reset --hard commit_id|A
reset 参数解析
- --mixed (默认值) 恢复到工作区修改 需要 add commit (不会改变工作区文件)
- --soft 恢复到暂存区 需要 commit (不会改变工作区文件,建议使用)
- --hard 恢复到工作区 需要 change add commit
(由于绝大多数情况到工作区是不可逆的,切记恢复到工作区最好先做备份,一般情况下不要用--hard,版本回退也需要做好备份再进行--hard回退)
注意: 最后版本回退需要进行分支替换而不是提交,版本回退由项目总负责人评估操作,一般人员需报备给项目总负责人(最好使用gitlab的权限控制,禁止普通研发人员删除分支)
远端仓库
场景一: 本地仓库与远端仓库
graph LR
C[本地仓库]
CP[remote]
D[远端仓库]
C-->|push|D
C-->|remote add|D
D-->|clone|C
D-->|pull|C
D-->|fetch|CP-->|merge|C
冲突
冲突发生原因
情景一
用户A 从 master 分支 拉取代码 并自建 A 分支 A 的头指针 为 master 的头指针 为 1 用户B 从 master 分支 拉取代码 并自建 B 分支 B 的头指针 为 master 的头指针 为 1 A 修改了 src 下的 test.txt 文件 第二行 为 ttt 并进行提交并合并到 master 分支 master分支和A分支 头指针从 1 指向 A_2 B 修改了 src 下的 test.txt 文件 第二行 为 bbb 并进行提交 合并到 master 分支 合并过程中发生冲突 B 指针 从 1 指向 B_2 master 合并失败
分析 A 修改了 src 下的 test.txt 文件 第二行 为 ttt 并提交合并到主分支 master分支和A分支 头指针从 1 指向 A_2 B 修改了 src 下的 test.txt 文件 第二行 为 bbb 并提交合并到主分支 此时B分支指针由 1 指向 B_2 master 会从 1 -> A_2 和 1 -> B-2
master 会将 A_2 和 B_2 进行合并 成功后 将合并结果写到 master 分支 合并过程中 A 说 src 下的 test.txt 文件 第二行 为 ttt, 但是 B 说 src 下的 test.txt 文件 第二行 为 bbb git 不知道 A 是最终结果 还是 B 是最终结果,认为 A 和 B 之间产生了冲突,由于A已经合并,那么 git 会告知 B 他和 A 产生冲突不可以合并代码,B 需要找 A 确认 src 下的 test.txt 文件 第二行 是什么, 并将最终合并结果告知git 进行合并。 总结: 不同分支在第一个共有指针之后 同时 修改 同一文件 的 同一行 并且 修改内容 不同 产生冲突
情景二
用户A 修改了 src 下的 test.txt 文件 第二行 为 111 后储藏库(stash) 储藏库 存储的是 指针 1 -> s1 用户A 修改了 src 下的 test.txt 文件 第二行 为 222 并提交(commit)A 分支 从 1 -> A1 用户A 从 储藏 拿出 src 下的 test.txt 文件 第二行 为 111 1->A1 1-s1 进行合并发现冲突 此时 git 在本地仓库记录的src 下的 test.txt 文件 第二行 为 222 但是 git 从储藏库拿出来的 src 下的 test.txt 文件 第二行 为 111 git 说不能判定 src 下的 test.txt 文件 第二行 的内容,需要用户A手动判定后通知Git进行合并 总结: 相同分支 在第一个共有指针之后 同时 修改 同一文件 的 同一行 并且 修改内容 不同 产生冲突
冲突解决
- 将代码改好后进行提交
- 通过编辑器进行冲突合并并提交(推荐)
提交规范
commit 规范
feat - 新功能 feature
fix - 修复 bug
docs - 文档注释
style - 代码格式(不影响代码运行的变动)
refactor - 重构、优化(既不增加新功能,也不是修复bug)
perf - 性能优化
test - 增加测试
chore - 构建过程或辅助工具的变动
revert - 回退
build - 打包
开发习惯
- 开发前首先同步远端仓库
- 推送远端前需同步远端仓库
- 开发完小功能需要提交并写好备注和标识
- 开发完大功能需要推送并提交合并请求,需要写好FAQ文档
- 一天结束需要提交代码的就要提交代码不能拖沓