Git 的基本使用方法
Git 基本概念
- 工作区:仓库的目录。工作区是独立于各个分支的。
- 暂存区:数据暂时存放的区域,类似于工作区写入版本库前的缓存区。暂存区是独立于各个分支的。
- 版本库:存放所有已经提交到本地仓库的代码版本
- 版本结构:树结构,树中每个节点代表一个代码版本。
.git 文件的目录结构
- HEAD:存储当前指向的分支节点
- config:存储 git 项目的配置
- objects:存储文件信息
- refs:存储分支信息
Git Config
git 中的配置分为三个级别,分别是 --global, --systems, --local 这三个级别的配置可能会重复,低级别的配置会覆盖高级别的配置。级别从高到低: --systems,–global,--local。
用户名配置
git config --global user.name ""
git config --global user.email ""
Git 别名配置
git config --global alias.cin "commit --amend --no-edit"
查看 Remote
git remote 用于连接本地和远程仓库,通过该命令可以设置代码的 pull/fetch 源
git remote -v
可以看到增加的源以及他们的类型 fetch/push 。于是我们可以单独设置 push/fetch 的源
git remote add origin git@github...(添加一个叫做origin的源)
git remote set-url --add --push origin git@github....(单独设置了一个push的源)
git remote -v # 查看效果
可以看到同样是 origin 的源,push/fetch 地址不一样了。
Http Remote 免密配置
Http 连接方式的免密配置有两种:一种是将密码存储内存中,一种是存储在硬盘里
- 内存配置:
git config --global credential.helper 'cache --timeout=3600' - 硬盘配置:
git config --global credential.helper "store --file/path/to/credential-file"不指定目录的情况下默认存储在~/.git-credentials中
一般不推荐使用 Http 连接。
SSH Remote
通过公私钥方式访问,将公钥存储在服务器,携带私钥访问服务器,从而实现免密访问。目前的 Key 有四种类型: dsa,rsa,ecdsa,ed25519 默认使用 rsa , 由于一些安全问题,推荐使用 ed25519。
ssh-keygen -t ed25519 -C "your_email@example.com" # 生成密钥,默认存储在~/.ssh/id_ed25519.pub
Git 常用命令
git init
在某个文件夹下,初始化本地仓库,会生成一个 .git 文件。
git add
git add . # 将所有的待加入暂存区域的文件存入暂存区
git add xxx # 将某个具体的文件存储暂存区
git add 添加的文件会保存一份在 .git/objects 下 ,新增一个以文件ID命名的文件,使用 git cat-file -p <文件ID> 可以查看文件里面的内容,里面保存的就是刚刚添加的文件内容。
git commit
git commit -m "xxx" # 将缓存区的内从提交到当前分支
git commit 之后,在 .git/objects 下就会生成三份文件。查看三份文件具体信息会发现他们有个前缀标签:一下三种文件统一称为 object
- Blob : 存储文件的内容
- Tree: 存储文件的目录信息
- Commit: 存储提交信息
git 通过 Commit 寻找 Tree 信息,每个 Commit 都会存储对应的 Tree ID,通过 Tree 存储的信息,获取到对应的目录树信息,再从 tree 中获得 blob 的ID,通过Blob ID 获取对应的文件内容。
git branch
git checkout -b <branch-name> # 可以创建一个新分支
分支一般用于开发阶段,是可以不断添加 commit 进行迭代的。它的 ref 指向的 Commit 代码版本经常变更。
git tag
git tag -a <tag-name> # 生成一个tag
标签一般表示一个稳定的版本,他的 ref 指向一个稳定的 Commit 不会更改,一般用于发布一个大的版本。开发的过程中小的功能开发,特性增加一般使用 branch ,当一个大版本完成需要发布的时候一般使用 tag。
回溯历史版本
使用 git reset --HEAD^ 或者 git reset --hard HEAD~ 可以将代码回滚到上一个版本,其中 HEAD 后面跟几个 ^ 就可以退回几个版本,也可以使用 git reset --hard 版本号 直接回退到某个版本。
修改历史版本
-
使用
commit -amend可以修改上一次的commit的信息,修改之后,commit id会发生改变 -
可以使用
git rease -i HEAD~3可以对最近的三个commit的修改。-
可以合并这三个 commit
-
可以调整三次commit的顺序
-
可以修改或者删除
-
提交和拉取
git clone
拉取完整的仓库到本地,可以指定分支,深度。
拉取代码
可以使用 git fetch 或者 git pull 两种方法将远程仓库中的代码拉取到本地。其中的区别是:
fetch将最新代码拉取到本地后不会执行merge操作,需要手动合并代码pull会自动合并代码,等同于fetch + merge
git pull 产生的一部分冲突处理
如果在开发的过程中,需要进行 git pull 来更新本地代码版本,而工作区或者暂存区中有为提交的代码。可以使用 git stash 将未提交的代码存入一个栈中。
git stash # 将工作区和暂存区的代码存入栈中
...
这里可以执行 git pull 操作
...
git stash pop # 将站定的修改恢复到当前分支,并删除栈顶元素
git statsh list # 查看栈中所有元素
git push 提交代码
使用 git push origin <banch-name> 将代码提交到指定分支。如果本地的 commit 和远程仓库的历史不一样,就会产生冲突。如果是个人开发,可以加上 -f 参数强行推送(一般不推荐,尤其在团队开发中)
git 的 GC 机制
当我们写了很多版本的代码后,就会产生很多的 Object 文件,而只有当前版本的 Object 或者分支上最近的一个版本,有 ref 指向他们。而其他没有 ref 指向的 Object ,被称为悬空的 Object。为了减少空间损耗,我们可以删除一些不需要的 Object。
GC
通过 git gc 可以删除不需要的 object 并且会对 object 进行打包压缩,减少仓库的体积。通过 git gc prune=now 可以指定删掉多久之前的对象,默认是两周前
Reflog
reflog 是用于记录操作日志的,防止误操作后数据丢失。可以手动将日志设置为过期。
Git 研发流程
这里主要记录 Github Flow – 分支管理工作流
Github 工作流只有一个主干分支,基于 Pull Request 的方式往主干分支中提交代码。主干分支一般是不会删除代码的。在团队合作中,有以下两种合作方式:
- owner 创建好仓库后,其他用户通过 Fork 方式创建自己的仓库,并在 Fork 的仓库上开发,通过提交 PR 往主库中合并代码。这种方式一般在开源项目中使用。
- Owner 创建好仓库后,将团队内的队友加入,分配权限后在同一个仓库内进行开发,这种方式比较适合公司内部或者认识的人之间开发。
工作流
- 创建一个 feature 分支
- 创建一个 feature 分支到 main 分支的 Pull Request
- 在 Pull Request 页面执行 CI / CA / CR 等操作后,都检查通过后,将 feature 分支合入 main 分支。
CI 是 Continuous Integration 的简写,是在源代码变更后自动检测、拉取、构建和进行单元测试的过程。通常包括测试,构建,测试,部署等过程。
于是就完成一个完整的代码提交流程。