目录图
一、
二、
主要
基础篇
(1)git commit
Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅许多!
Git 希望提交记录尽可能地轻量,因此在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。
Git 还保存了提交的历史记录。这也是为什么大多数提交记录的上面都有父节点的原因 —— 我们会在图示中用箭头来表示这种关系。
对于项目组的成员来说,维护提交历史对大家都有好处。
git commit
(2)git branch
Git 的分支也非常轻量。它们只是简单地指向某个提交纪录 —— 仅此而已。所以许多 Git 爱好者传颂:
早建分支!多用分支!
这是因为即使创建再多的分支也不会造成储存或内存上的开销,并且按逻辑分解工作到不同的分支要比维护那些特别臃肿的分支简单多了。
在将分支和提交记录结合起来后,我们会看到两者如何协作。现在只要记住使用分支其实就相当于在说:“我想基于这个提交以及它所有的父提交进行新的工作。”
# 创建新分支
git branch newBranch
# 切换分支
git checkout <name>
# 创建并切换到分支
git checkout -b wangting_test
(3)git merge
在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个父节点。翻译成自然语言相当于:“我要把这两个父节点本身及它们所有的祖先都包含进来。”
git branch bugFix
git checkout bugFix
git commit
git checkout main
git commit
# 当前分支合并bugFix
git merge bugFix
(4)git rebase
第二种合并分支的方法是 git rebase。Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
# 我们想要把 bugFix 分支里的工作直接移到 main 分支上。移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的。
# 把当前分支的commit移到main分支上
# 或者说:把当前分支开始的节点 挪到 main分支最后 (merge:把别的分支合并到当前分支)
git rebase main
# rebase操作遇到冲突:
# Resolve all conflicts manually, mark them as resolved with
# "git add/rm <conflicted_files>", then run "git rebase --continue".
# You can instead skip this commit: run "git rebase --skip".
# To abort and get back to the state before "git rebase", run "git rebase --abort".
高级篇
(1)分离HEAD
我们有必要先学习在你项目的提交树上前后移动的几种方法。
HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。
HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。
# 如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看
# 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向
分离的 HEAD
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:
git checkout 分支
git checkout commit
(2)相对引用 (^)
git log 来查查看提交记录的哈希值。
哈希值可能是:fed2da64c0efc5293610bdd892f82a58e8cbc5d8
Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符
通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用。这个就很厉害了!
使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。
相对引用非常给力,这里我介绍两个简单的用法:
使用 ^ 向上移动 1 个提交记录
使用 ~<num> 向上移动多个提交记录,如 ~3
(3)相对引用2 (~)
“~”操作符
如果你想在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,Git 当然也考虑到了这一点,于是又引入了操作符 ~。
该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次)
git branch -f main xxx
强制修改分支位置
我使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:
git branch -f main HEAD~3
上面的命令会将 main 分支强制指向 HEAD 的第 3 级父提交。 注意:当前分支不能是main分支
(4)撤销变更 git reset
主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。
git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset –mixed(默认) –soft –hard
git reset –mixed xxx : 之前commit文件回到工作区;
git reset –soft xxx: 之前commit的文件回到暂存区;
git reset –hard xxx: 之前commit的文件没了。
移动提交记录
(1)Git Cheery-pick
到现在我们已经学习了 Git 的基础知识 —— 提交、分支以及在提交树上移动。 这些概念涵盖了 Git 90% 的功能,同样也足够满足开发者的日常需求
然而, 剩余的 10% 在处理复杂的工作流时(或者当你陷入困惑时)可能就显得尤为重要了。接下来要讨论的这个话题是“整理提交记录” —— 开发人员有时会说“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”, 而接下来就讲的就是它的实现方式,非常清晰、灵活,还很生动。
看起来挺复杂, 其实是个很简单的概念。
本系列的第一个命令是 git cherry-pick
, 命令形式为:
git cherry-pick <提交号>...
如果你想将一些提交复制到当前所在的位置(HEAD
)下面的话, Cherry-pick 是最直接的方式了。我个人非常喜欢 cherry-pick
,因为它特别简单。