EP29-zake学Git

232 阅读8分钟

参考文档:

  1. 图解 Git 基本命令 merge 和 rebase

  2. 学习git分支管理

  3. 学习git分支管理2

  4. Pro git

  5. Git Community Book 中文版

  6. 解析.git文件夹,深入了解git内部原理

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
  1. master 与 feature分支无交叉

image.png

git checkout master
//默认使用fast-forward方式
git merge feature

//不分叉的场景也可以使用 no-ff, 会有新的commit生成。
git merge feature --no-ff

默认情况下,merge执行快进式合并,会直接将master分支指向feature分支。
使用--no-dif参数后,会执行正常合并,并会在master分支上生成一个新的commit。为了保证版本演进的清晰,建议采用这种做法。

  1. master与feature分支有交叉 默认会采用 no-ff方式
2,使用变基rebase

变基就是改变当前分支的起点,rebase后面跟的就是基分支。
变基前:

image.png 变基后:

使用git rebase master feature image.png 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命令复制一个提交节点,并在当前分支做一次完全一样的新提交。

image.png

2,切换分支

git checkout

参考文档:

//当checkout即没有指定文件名,也没有指定分支名,而是一个标签,远程分支,
//SHA-1值或者是像main~3类似的东西,就得到一个匿名分支,称作detached HEAD(被分离的HEAD标识)

image.png HEAD标识处于分离状态时的提交操作
当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。

image.png

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, 工作中用到的命令

  1. 删除本地分支
//查看本地分支
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)