前言
Git 同学们都非常熟悉了,但是用来用去,可能就是提交、推送、合并这些简单的操作,偶尔需要使用一些稍微复杂的命令时,需要百度一下,虽然能搜到,但是零零散散,所以本篇整合了博主自己常用的 Git 命令,可能不是那么全面,但是已经足够使用。
基础 git 操作
git init
sh
# 初始化 git 仓库,将本地某个文件夹变成 git 仓库,
git init
其内部会添加一个 .git 的目录,表示已经初始化成功。
这样就表示初始化 git 仓库成功了。这里的提示是告诉我们设置默认的分支名,因为我本地默认分支是 master,git 推荐使用 main、trunk 这样的分支名。
git clone
sh
# 表示从指定的 git 地址克隆项目到本地。git url 的地址可以是 https、git 或者是 SSH 协议的 server@username 这种有效的地址。
git clone [addr]
除此之外,您的仓库可能用到了 submodule,这个时候克隆仓库,需要带上 --recurse-submodules
,会递归的克隆 submodule 的仓库。
submodules 其实就是子包,意思是当前仓库下面还有另外一个仓库,后面会细说 submodule 的用法。
git remote
远程仓库的常用命令。
比如将本地仓库关联到远程仓库,可以执行
sh
git remote add origin [remote url]
# 查看关联的远程仓库的名称及地址
git remote -v
# 移除关联的远程仓库
执行结果如下
git remote remove [repo name]
则可以移除关联的远程仓库。
git remote rename [old name] [new name]
可以重命名远程仓库的名称。
git add
关联好远程仓库以后,就可以添加文件进行开发了,新增一个 README.md 文件,里面随便添加一点内容,然后在 vscode 中可以发现出现了该文件的记录
可以看到文件右侧有一个 U
的标记,表示 untracked
未跟踪的,意思是该文件还没有被 git 所跟踪。
sh
# 将 README 文件纳入 git 跟踪并且被暂存
git add README.md
# 将所有新增、移除或者被修改文件放入暂存区中
git add .
# 将 README.md 移出暂存区,如果没有 --cached 命令,则该文件会被删除,不过可以通过 git 恢复回来
git rm README.md --cached
git commit
接着暂存区中的文件就可以被提交了。
sh
# 提交暂存区的文件
git commit
此时会进入 vim 编辑器
第一行就是输入提交信息的地方,其他 # 开头的都是注释信息。
git commit -m [message]
则是在一行中输入提交信息,换句话说,就是不会显示 vim 的编辑器形式,直接命令行输入要提交的信息就可以了。
--amend
选项可以重新编辑我们刚刚提交的信息。
-a
则可以不经过 git add
命令就能将所有修改的文件纳入暂存区并提交。和 -m
选项使用时,注意前后顺序,需要按照这样的顺序:
sh
git commit -a -m 'commit message'
git push
sh
# 将当前提交推送到远程仓库的某个分支下。
git push origin master
查询命令
git status
sh
# 查看当前提交状态
git status
# 查看当前所在分支
git status --branch
git log
sh
# 查看提交记录
git log
# 查看最近 n 个提交
git log -n
git cherry-pick
submodule 命令
submodule 字面意思就是子模块,在一个 git 项目中,存在另外一个 git 项目,这个时候另外的 git 项目就是作为子包来使用的,通常子包作为公共包,比如公共方法、组件等。
下面就是子包设计到的 git 命名,添加子包、更新子包、移出子包
git submodule add
sh
# 添加子包到当前项目中
git submodule add [url] [path]
这个时候,当前项目会出现 path
路径的文件夹以及 .gitmodules
的文本文件,文件中展示了子包的相关信息
git submodule update
因为子包作为一个单独的仓库,也是会被修改更新,因此依赖了子包的项目如果要更新子包的内容,则需要执行:
sh
# 拉取远程子包的内容到本地
git submodule update --remote
git submodule deinit
sh
# 删除 .git 文件夹中的 modules 配置信息
git submodule deinit git-cli-submodule
# 上面只是删除了配置信息,还需要删除本地的子包目录
git rm git-cli-submodule
最后提交修改就彻底删除了子包。
如果是 clone 带有子包的项目,就是文中开头提到的 --recurse-submodule
参数就可以同时 clone 主包和子包了。
分支命令
git checkout
sh
# 创建 develop 分支并切换到该分支
# 这个命令是以下两个命令的简写
# git branch develop
# git checkout develop
git checkout -b develop
# 切换到指定的main分支
git checkout main
git branch
sh
# 查看当前所在分支,注意后面不带任何参数
git branch
# 删除本地分支
git branch -d develop
# 如果删除失败,可能是当前分支还有未合并的内容,可以使用 -D 参数强制删除
git branch -D develop
# 删除远程分支
git push origin --delete develop
标签命令
标签可以理解为某个提交做一个标记,一般用来标记仓库的版本号,这点我们可以经常在开源的项目上看到。
标签命令主要包含以下几个常用命令:
sh
# 查看所有的标签
git tag
# -a 表示附注标签,可以添加 -m 参数存储标签备注信息
# git tag -a v1.0 -m 'version 1.1'
# 不加 -a 参数表示轻量标签
# git tag v1.0.0
# 删除标签
git tag -d v1.0
# 删除远程仓库标签
git push origin --delete v1.0
# 可以利用标签,切换到标签指向的提交
git checkout v1.0
轻量标签很像一个不会改变的分支------它只是某个特定提交的引用。
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。但是如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。
合并命令
合并可以理解为将一个分支的内容合并到另外一个分支上,合并也存在多种合并方式,下面来一一介绍。
git pull
git pull 是一种比较暴力的合并方式,实际上它是下面两个命令的合并执行:
sh
# 从远程仓库抓取本地没有的数据,注意它并不会改变本地的数据
git fetch
# 抓取到远程的数据以后,合并远程仓库的内容
git merge
这种合并就是将两个不同走向的分支强制交叉到一起,因此合并以后的走向大概是这样的:
feature 分支合并到 main 分支以后,main 的历史记录里面就会出现交叉合并的历史。
如果不想这么合并,可以选择 rebase 命令。
git rebase
sh
# 切换到要合并的分支上
git checkout feature
# 基于 main 分支进行变基
git rebase main
# 可能会出现冲突,解决完冲突以后,继续变基
git rebase --continue
# 如果想要取消变基,则可以这么做
git rebase --abort
# 完成变基以后切换到主分支
git checkout main
# 合并功能分支
git merge feature
所谓变基,就是以 main 分支为基准,将 feature 上修改的内容合并到 main 上。乍一听,不是和 merge 是一样的吗?实际上以 main 为基准,就是先找到 main 和 feature 的公共祖先节点,再将二者的修改记录一一放到这个公共祖先节点的后面。
文字可能不太好理解,下面看一个示意图:
从结果来看,最后的提交记录是一条直线,而不是像上面那样出现分叉。这么合并的作用也很显而易见,提交历史更加清晰,不会有分支提交里面的那么多细节。
变基有优点也有缺点。变基的缺点就是,变基基于你自己的仓库或分支进行变基,如果变基的内容是别人基于此进行开发的,那么变基会导致他们修改的记录丢失,后续别人合并的时候,会导致更多冲突,而别人需要花费更多的时间来解决这些冲突,所以你要确保变基的内容是独属于你自己的。
除了变基合并,还可以利用 rebase 来合并提交历史记录。
简单来说,就是我们提交的历史记录中,很多都是没有实际意义的内容,比如单词拼错了,修改了一个单词,忘记添加了一个分号这种,会导致历史记录中存在大量这样意义不大的提交,而我们只希望是关键功能点、修复 bug、性能优化这些重大提交,此时就可以将一些不必要的提交合并到一起。
比如这里我要合并前三个提交
sh
# 合并前三个提交的后一条记录的 SHA 值来合并前面所有的提交历史记录
git rebase -i fea123a3
之后会在编辑器中显示了要提交的三个记录:
每个提交信息前面的 pick 可以替换为 command 的选项。这里我们希望保留第一个记录,剩下两个 pick 信息可以修改为 f(fixup 的简写)。
保存退出以后,强制提交来覆盖原来的记录就可以了。
撤销操作
git 将我们的项目划分为三个树,工作区、暂存区以及 HEAD 指针指向当前分支最近一次提交,而撤销操作也就是改变这三个树的状态。
sh
# 重置到上一次提交,实际上就是改变了 HEAD 指针的指向了上一次提交,暂存区和工作区不变
git reset --soft HEAD~
# 同样重置到上一次提交
# 区别在于此时暂存区也指向了上一次提交,工作区则变成了 git add 和 git commit 之前的样子
# 默认不加 --mix 选项也是这样的效果
git reset --mix HEAD~
# 重置到上一次提交
# 此时工作区、暂存区以及 HEAD 都会指向上一次提交
# 换句话说,本地的修改的内容都会被上次提交所覆盖,也就是本次的修改都没有了,所以这是一个危险操作
git reset --hard HEAD~
reset 的操作会覆盖原来的提交记录,产生新的提交。如果想要保留原来的提交记录,可以使用 revert 命令。
sh
# 会在原来的记录后面新增一条新的记录
git revert HEAD
后语
以上,就是博主开发中经常用到命令,更多的细节可以参考 git官方文档。如果有错误之处,还望不吝指教。