参考文档:
1,用法
1, git 基础
git add
// 将工作区的files文件添加到暂存区
git add files
// 将当前更改的所有文件添加到暂存区
git add .
git checkout
//将暂存区中files覆盖工作区中的files
git checkout -- files
//将最后一次commit中的files覆盖工作区中的files
git checkout HEAD -- files
git reset
//撤销暂存区中的所有修改
git reset
//将上次commit的files文件覆盖暂存区中的files
git reset -- files
git commit
//修改上次的提交,使用与当前提交相同的父节点进行一次提交,旧的提交会被取消
git commit --amend
git pull
//从远程仓库拉取代码并合并到本地,可简写为git pull等同于git fetch && git merge
git pull <远程主机名> <远程分支名>:<本地分支名>
//使用rebase的模式进行合并
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
git fetch
与git pull不同,git fetch只会拉取远程的更改,不会自动进行merge操作。对当前代码没有影响。
# 获取远程仓库特定分支的更新
git fetch <远程主机名> <分支名>
# 获取远程仓库所有分支的更新
git fetch --all
git revert
反做,将某一次提交反做,生成一次新的提交。
与git reset的区别在于,git reset是取消最近连续几次的提交,而 git revert是某一次的。
git stash
git stash //把本地的改动暂存起来
git stash save "message" 执行存储时,添加备注,方便查找。
git stash pop // 应用最近一次暂存的修改,并删除暂存的记录
git stash apply // 应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} 。
git stash list // 查看stash有哪些存储
git stash clear // 删除所有缓存的stash
//显示做了哪些改动,默认显示第一个存储,如果要显示其他存储,后面加
//stash@{$num}, 比如第二个:git stash show stash@{1}.
git stash show
//从列表中删除某个存储,num从0开始。
git stash drop stash@{$num}
git xxx -h
获取xxx的详细用法。
2,git 分支
HEAD指向当前分支所在的快照。
HEAD~1指当前commit的父节点,可以简写为HEAD~
# 新建本地分支,但不切换
git branch <branch-name>
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看本地和远程分支
git branch -a
# 删除本地分支
git branch -D <branch-nane>
# 重新命名分支
git branch -m <old-branch-name> <new-branch-name>
1,分支合并
1, 使用merge
- master 与 feature分支无交叉
git checkout master
//默认使用fast-forward方式
git merge feature
//不分叉的场景也可以使用 no-ff, 会有新的commit生成。
git merge feature --no-ff
默认情况下,merge执行快进式合并,会直接将master分支指向feature分支。
使用--no-dif参数后,会执行正常合并,并会在master分支上生成一个新的commit。为了保证版本演进的清晰,建议采用这种做法。
- master与feature分支有交叉 默认会采用 no-ff方式
2,使用变基rebase
变基就是改变当前分支的起点,rebase后面跟的就是基分支。
变基前:
变基后:
使用git rebase master feature
git rebase命令通常称为向前移植。
git rebase master feature命令详解:
特性分支feature向前移植到了master分支上,把补丁变基到了master分支的头部。操作完后,可以发现master分支后面多了几个commit(与feature是不同的commit,但是修改的内容相同)。变基后,改变的只是feature分支,基分支的HEAD指针依然在之前的commit,这个时候需要将feature分支合入master分支,将master分支的HEAD指向刚刚合入的commit点。
git checkout master
git merge feature
git rebase命令最常用使用场景:
本地分支和远端对应分支之间的合并。
//本地master分支和远端master分支
//拉取远端分支
git fetch
//以远端分支为基变基本地分支
git rebase origin/master master
git rebase -i 的使用
3,merge与rebase的区别
变基是合并命令的另一种选择,合并是把两个父分支合并并进行一次提交,提交历史不是线性的。变基是在基分支上重演另一个分支的历史,提交历史是线性的。本质上是线性化自动的cherry-pick。
变基操作保留了该commit所作出的修改,但是删除了支链分支上一些现有的提交记录,删除了这些节点。 并在基分支生成新的提交。
merge分支杂乱,但是可以保留有价值的历史文档;rebase分支清晰,但是无法体现时间线。
具体需要根据使用场景来判断使用何种方法合并分支。
4,使用cheery-pick
cheery-pick命令复制一个提交节点,并在当前分支做一次完全一样的新提交。
2,切换分支
git checkout
参考文档:
//当checkout即没有指定文件名,也没有指定分支名,而是一个标签,远程分支,
//SHA-1值或者是像main~3类似的东西,就得到一个匿名分支,称作detached HEAD(被分离的HEAD标识)
HEAD标识处于分离状态时的提交操作
当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。
x, 使用规范
1,commit规范
- feat 新增功能。
- fix 修复bug
- docs 修改文档
- refactor 代码重构,未新增任何功能和修复任何bug
- build 改变构建流程,新增依赖库,工具(例如webpack修改)。
- style 仅仅修改了空格,缩进等,不改变代码逻辑。
- revert 回滚到上一个版本。
2,分支使用规范
- master 主分支,不能直接在主分支上修改和提交代码。
- develop 测试分支,所有开发完需要提交测试的功能合并到该分支。
- production 生产分支,所有测试完需要提交生产的功能合并到该分支。
- feature 开发分支,大家根据不同需求创建的功能分支,开发完成后合并到develop分支。
- fix bug修改分支,对已发布的版本进行漏洞修复。
2, 原理
参考文档:
1,存储信息的解析
2021年5月24日11:41:47
在objects文件夹中,会对每个文件都生成一个文件(没有明确的文件类型),文件中的内容是blob类型,这是第一种Git object,只存储一个文件的内容,不包括文件名等其他内容。保存的内容是经过哈希算法得到的哈希值。
当将内容commit之后,git仓库会新增一个object,这是第二种object类型---tree,它将当前的目录结构打了一个快照,它存储了一个目录结构,以及每一个文件的权限,类型,对应的身份证(哈希值),以及文件名。
然后还有第三种object类型---commit,储存的是一个提交的信息,包括对应目录结构的快照tree的哈希值,上一个提交的哈希值,提交的作者,提交的时间,提交的信息。
分支信息是存储在.git/refs/文件夹下的。
在git仓库里面,head、分支、普通的tag可以理解为一个指针,指向对应的commit的哈希值。
Git本质上是一个key-value的数据库加上默克尔树形成的有向无环图。
相关问题
每次commit,git存储的是全新的文件快照还是储存文件的变更部分
Git存储的是全新的文件快照,而不是文件的变更记录。就算只在文件中添加一行,Git也会创建一个全新的blob object。
3, 工作中用到的命令
- 删除本地分支
//查看本地分支
git branch
//删除本地分支
git branch -D xxx
4, git操作中遇到的问题
1,
公司搭建了 gerrit 代码审核服务器.在 git push 提交时,出现如下错误:
git.exe push --progress "origin" master:refs/for/master
Enumerating objects: 97, done.
Counting objects: 100% (63/63), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (25/25), 2.67 KiB | 105.00 KiB/s, done.
Total 25 (delta 10), reused 9 (delta 0)
remote: Resolving deltas: 100% (10/10)
fatal: Unpack error, check server log
error: remote unpack failed: error Missing tree 3771ac436087f881450e12e8f41791652ba0a505
To ssh://gerrit.xxx.com.cn:29418/xxxxx/xx/xxxxxxxx
! [remote rejected] master -> refs/for/master (n/a (unpacker error))
error: failed to push some refs to 'ssh://10000000@gerrit.xxx.com.cn:29418/xxxxx/xx/xxxxxxxx'
解决方法来自 stackoverflow.
使用如下命令即可推送成功:
git push --no-thin "origin" HEAD:refs/for/master
关键点是 --no-thin 选项. stackoverflow 上的那位答主这么解释的:
默认情况下 git push 会在向服务器推送时进行优化,以将所发送的包降低到最小. 做法是发送时忽略本地仓库和远端仓库中共有的部分. 即 git push 默认是采用 --thin 选项的.
发生本文中出现的问题,貌似是因为某个 git 对象和服务器不一致了.
这时加上 --no-thin 参数,把该传的都传过去,问题就解决了.
2,git拉取库太大导致失败
解决方法:
git config –-global http.postBuffer 524288000
(单位b 此500M)