Git是一个开源的分布式版本控制系统,可以有效、高速的处理从小到非常大的项目版本管理(管理源代码的)
git 开发初期是用来管理 linux 内核版本的,发明者也是 linux 之父
通过 hash 算法输出一个固定长度的 哈希值,比较两者 git 就知道是文件否变动过
安装
- 安装:
gitbash.exe
- 项目本地仓库 :
git init
!!!注意,如果不是脚手架帮忙 init,每个项目都要先初始化才可以版本控制
GIT 基本原理
- 哈希
哈希是一系列算法,是散列算法,也有叫摘要算法。不同哈希算法强度不同,但有一些共同点:- 不管输入的数据量,输出固定长度
- 输入确定,输出确定,修改输入,输出就改变,通常改变很大
- 不可逆
git 底层采用了 SHA-1 算法,除此之外还有 md5。可能我们在下载软件的时候会见到类似 md5 校验的东西,就是将最初的 md5 与你下载后文件的 md5 核对文件或者压缩包,如果不一致很可能文件被修改或损坏
- 版本保存机制
- svn 是集中式管理机制,将每个版本的修改保存起来,然后将当前修改+历史修改+源文件拼在一起给你,是增量式版本控制,不会保存大量重复的数据,每个版本只保存有变化的地方。这样可以很好的节约服务器空间。
- git 是快照流,每个版本将本地所有文件快照保存,每个快照之间重复的文件会有指针指向之前的版本
- git 每个文件都会有一个 hash 。所有文件的 hash 值构成一个 tree 结构,包含每个文件以及 hash,tree也有自己的 hash 。每个 commit 包含 tree,commit 也有一个自己的 hash,也有上一个 parent 的hash 。类似区块链的比特币
- 第一次提交会有 root commit ,接下来的所有提交的parent都会指向最后的 root commit
- 当新建基于当前分支的新分支时,svn 会整个复制下来,git 会新建一个指针指向之前的分支。类似所有分支只是一个栈的一个放指针的空间,git 主体是一个引用类型,新建分支后会新开一个栈空间存放同样的指针
- 切换分支只是将 HEAD 切换到哪个指针上(分支)
- 各个提交之间通过 parent 形成紧密连接,从数据结构上说这也是一个链表
commit size
tree 82wc2
parent hash
author juf
committer juf
Commit Message 规范
fix; fix some bug
feat: 新增xx功能
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动
查看当前状态
git status
查看日志
git log 最完整的日志输出
commit id
commit xxxx
Author: user infor
Date xxxxx
commit message
insert xxxx edit
git log --pretty=oneline 简写 git log --oneline
git log --oneline 显示的日志只哈希值比 git log --pretty=oneline 少几位
8a8714e (HEAD -> master) Merge branch 'pro'
bcfc88e (pro) change b
688ca60 delete c
cbc439a merge b
2275de9 change b
74d07da Merge branch 'pro'
...
git reflog 显示版本之间 head指针关系,提交信息
8a8714e (HEAD -> master) HEAD@{0}: checkout: moving from pro to master
bcfc88e (pro) HEAD@{1}: checkout: moving from master to pro
8a8714e (HEAD -> master) HEAD@{2}: merge pro: Merge made by the 'recursive' strategy.
cbc439a HEAD@{3}: checkout: moving from pro to master
bcfc88e (pro) HEAD@{4}: commit: change b
688ca60 HEAD@{5}: commit: delete c
...
版本回滚
git reset
参数 | 作用 |
---|---|
git reseat --soft | 只回退仓库版本(指针),暂存区和工作区版本不回退 |
git reseat --mixed | 只回退仓库和暂存区版本,工作区不回退 |
git reseat --hard | 仓库,暂存区,工作区版本都回退 |
方式:
- 基于索引操作(推荐)
- 使用 ^ 符号只能后退
- 使用 ~ 符号只能后退
git reset --hard HEAD^^^
git reset --hard HEAD~3
git reset --hard 8a8714e
git diff [ file ]
不指定文件默认展示当前所有工作区文件与暂存区比较
当使用 git add 将工作区保存到暂存区后 git diff 比较暂存区没有输出
命令 | 说明 |
---|---|
git diff | 工作区与暂存区比较 |
git diff HEAD | 工作区与本地库比较 |
git diff hash | 工作区与某个版本比较 |
git diff HEAD^^^ | git diff HEAD~n |
git 以行为单位记录变化,当你只是在一行后添加一些东西,git 会认为整行变化
a.js
aaaaa -> aaaaa // 注释
git diff a.js
-aaaa
+aaaa // 注释
GIT MERGE
在合并外部分支时,你应当保持自己分支的整洁,否则的话当存在合并冲突时将会带来很多麻烦
为了避免在合并提交时记录不相关的文件,如果有任何在index所指向的HEAD节点中登记的未提交文件,git pull 和 git merge 命令将会停止
当产生合并冲突时,该部分会以<<<<<<<
,=======
和 >>>>>>>
表示。在=======
之前的部分是当前分支这边的情况,在=======
之后的部分是对方分支的情况
- 切换到要主分支
- git merge feature_branch
假设分支历史节点结构如下,并处在 Master 分支上
Master
|
C-D
/
A-B
\
E-F-G
|
Feature
那么 git mrege Feature 会将 Feature 分支上自二者共同节点 B 之后的所有节点合并到 Master 上。直到Feature分支当前的commit节点(G节点),并位于Master分支的顶部。并且沿着Master分支和Feature分支创建一个记录合并结果的新节点,该节点带有用户描述合并变化的信息。
D 和 G 都是 F 节点的父节点
C-D
/ \
A-B F - Master
\ /
E-F-G
|
Feature
如果有冲突,git 不会帮你合并,需要手动解决冲突合并( git 有快速合并和另一个合并两种模式 忘记了)
git-merge命令中,有以下三种使用参数:
git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
git merge <msg> HEAD <commit>...
git merge --abort
git clone
git clone 下来远程仓其实做了三件事
- 初始化仓库
- 添加远程仓地址
- 拷贝远程仓文件到本地
git pull
pull = fetch + merge
fetch 将文件抓取下来,不自动合并到本地分支中去
merge 将远程各分支内容合并到本地各分支中
code | 说明 |
---|---|
git init | 初始化git |
git config --global user.name "your_name" | 添加全局用户名配置 |
git config --global user.email "your_mail" | 全局邮箱配置 |
git clone [url] | 从远程端复制项目 master |
git clone -b [branch_name] [origin_name] | 复制远程指定分支 |
git pull [origin_name] [branch_name] | |
git add . || [ file_path ] | (添加所有文件/单个文件到暂存区) |
git commit -m '注释' | 暂存区-本地仓库,注释必须写 |
远程仓操作
code | 说明 |
---|---|
git remote add [origin_name] [origin_url] | 添加远程源 |
git remote -v | 查看所有源 |
git remote rm origin_name | 删除对应源 |
git remote show | 查看远程端信息 |
git pull origin branch | 将远程仓内容合并到本地 |
git config --system --unset credential.helper | 如果密码错误报错输这个 |
git push [origin] [master] | 上传到远程端 |
git push -u origin branch | 提交本体仓到远程 |
分支
code | 说明 |
---|---|
git checkout -b branch_name | 创建from当前分支的新分支,并切换到新分支 |
git branch | 查看所有本地分支 |
git checkout branch_name | 切换分支 |
git status | 查看git状态 |
git log | 查看提交日志 |
git log --oneline | 查看提交说明 |
git reset --hard HEAD^ | 回退上一个版本 |
git reset --hard hash六位 | 回退任意版本 |
.gitignore | git忽略的文件或目录 |
git diff | 查看修改了哪里 |
git branch name | 创建新分支 |
git checkout branch_name | 切换分支 |
远程分支
code | 说明 |
---|---|
git branch -d branch_name | 删除本地分支 |
git push --delate origin branch_name | 删除远程分支 |
一些概念
git pull
= git fetch
+ git merge
fetch 是拉取远程分支的内容下来
merge 是合并操作
SSH key
- 检查SSH:
cat ~/.ssh/id_rsa.pub
- 生成 SSH:
ssh-keygen -t rsa -C " your email"
https://blog.youkuaiyun.com/u011925641/article/details/79897517
https://www.cnblogs.com/superGG1990/p/6844952.html
大小写
git默认大小写不敏感,有时候改文件夹名字大小写git不能正确处理,导致上传到仓库不起作用。
设置大小写敏感:git config core.ignorecase false
查看大小写设置:git config --get core.ignorecase
Git字母含义
M==Modified==文件被修改
C==Conflict==(内容)有冲突
A==Newly Added==新添加
D==Deleted==已删除
A: 增加的文件.
C: 文件的一个新拷贝.
D: 删除的一个文件.
M: 文件的内容或者mode被修改了.
R: 文件名被修改了。
T: 文件的类型被修改了。
U: 文件没有被合并(你需要完成合并才能进行提交)
X: 未知状态。(很可能是遇到git的bug了,你可以向git提交bug report)
Vscode 的 Git 工具
目前还在探索,有时会出问题
很好用 ctrl + shift + p 然后键入 git 可以看到所有支持的 git 命令
常见报错
git 出现 fatal: refusing to merge unrelated histories 错误
git pull 失败 ,提示:fatal: refusing to merge unrelated histories
这个问题是因为 两个 根本不相干的 git 库, 一个是本地库, 一个是远端库, 然后本地要去推送到远端, 远端觉得这个本地库跟自己不相干, 所以告知无法合并
使用这个强制的方法
git pull origin master --allow-unrelated-histories
--allow-unrelated-histories
把两段不相干的 分支进行强行合并
保留代码,删除分支内的所有 commit 记录
在日常开发中,有很多commit记录
创建孤立分支,没有任何提交记录,此时 git branch 没有该分支
git checkout --orphan last
git add .
创建一个 commit ,git branch 有该分支
git commit -m 'init'
删除 master 分支 -d 不行就 -D
git branch -d master
重命名分支为 master
git branch -m master
强推到远程仓 master 分支
git push -f origin master
创建没有任何提交记录的空白分支
git checkout --orphan branch_name
rm -rf .
// 添加 .gitignore Readme.md 等需要的文件
git add .
git commit -m 'init'
git 别名
新增别名:git config --global alias.trololo 'status'
删除别名:git config --global --unset alias.trololo
但是我不会如何查看配置过的东西,有会的留言,谢谢
fork & pull request
当你公司的项目遇到问题了,请求小王协助,但是小王不是你们公司的,没有远程仓的权力。这时小王需要 fork 复制你的远程仓到他的仓库里。然后小王再他复制的项目里修改好后,这时你的仓里并没有小王的成果。这时小王需要 pull request,然后你 merge 小王的代码到你的项目中。
以上纯属瞎编,没有实操
变基
本地想提交代码,git push 后提示远程端有别人新提交的代码,你需要先 git pull 下才可以 push
pull 后 push,git 会生成一个 merge 的 commit,很丑,如果不想这个东西,这样操作
git pull --rebase/-r
= git fetch + git rebase FETCH_HEAD
vscode 的 git 工具栏 - 拉取,推送-拉取(变基)
然后你可以在 vscode 的 git 栏看到你本地的 commit 排到了远程最新commit 的后边
- 远程端你提交了一个功能,但是后边发现一个bug。你想合并成一次提交
git rebase -i commit
然后剪切pick到你想要的顺序
https://zhuanlan.zhihu.com/p/145037478
git 比较子分支分离后的变化
比如 dev 分支从 master 分支切出来,进行了 n 个 commit,现在你需要对这些 commit 合并成一个 commit 统一 merege 到 master 分支内,则可以通过 git log master..dev --oneline
查看 dev 新的 commit
git 查询
git grep