一、基础篇
1、提交:git commit
git commit
2、创建分支: git branch
git branch [<分支名字>]
#比如:
git branch newImage
3、切换分支 :git checkout / git switch
说明:git 2.23+推荐使用git switch
git checkout <分支名>
# 或(Git 2.23+ 推荐)
git switch <分支名>
git switch <要切换的分支名字>
4、创建一个新的分支同时切换到新创建的分支:git checkout -b
git switch -b <新分支名字>
5、合并分支:git merge / git rebase
- 方法一:
git merge <要合并的分支>
# 将新分支bugFix合并到main分支
# 首先要先切换到main分支
git switch main
git merge bugFix
- 方法二:
git rebase
注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3’ 是我们 Rebase 到 main 分支上的 C3 的副本。
现在唯一的问题就是 main 还没有更新,下面咱们就来更新它吧……
# 目前存在两个分支bugFix(进行了一次提交)、main(进行了一次提交),目前在main分支,现要合并到main分支
# 首先要先切换到bugFix分支,再rebase到main上
git switch bugFix
git rebase main
# 或者直接将bugFix分支合并到main上
git rebase main bugFix
二、高级篇
1、分离的HEAD
- 我的理解就是:就是将原本指向分支,改为指向某个分支上具体的提交记录。
2、相对引用
^
操作符
比如,要想切换到bugFix分支的parent节点,那么可以这样做:
git checkout bugFix^
~
操作符
如果想在提交树中移动很多步的话,就可以使用~
操作符,该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次),指定向上移动多少次。
强制修改分支位置:git branch -f git
比如:以下命令会将main分支强制指向HEAD的第 3 级 parent 提交。
git branch -f main HEAD~3
3、撤销变更: git reset / git revert
需要先移动到本次要撤销提交的分支,再进行撤销提交操作。
- git reset
- git revert
三、拓展
1、 整理提交记录:git cherry-pick
到现在我们已经学习了 Git 的基础知识 —— 提交、分支以及在提交树上移动。 这些概念涵盖了 Git 90% 的功能,同样也足够满足开发者的日常需求
然而, 剩余的 10% 在处理复杂的工作流时(或者当你陷入困惑时)可能就显得尤为重要了。接下来要讨论的这个话题是“整理提交记录” —— 开发人员有时会说“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”, 而接下来就讲的就是它的实现方式,非常清晰、灵活,还很生动。
本系列的第一个命令是 git cherry-pick
, 命令形式为:
git cherry-pick <提交号>...
如果你想将一些提交复制到当前所在的位置(HEAD)下面的话, Cherry-pick 是最直接的方式了。我个人非常喜欢 cherry-pick,因为它特别简单。
咱们还是通过例子来看一下!
2、交互式的 rebase:git rebase -i
当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了 —— 没有比这更简单的方式了。
但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase —— 如果你想从一系列的提交记录中找到想要的记录, 这就是最好的方法了
交互式 rebase 指的是使用带参数
--interactive
的 rebase 命令, 简写为-i
比如:
git rebase -i HEAD~4
如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。
在实际使用时,所谓的 UI 窗口一般会在文本编辑器 —— 如 Vim —— 中打开一个文件。 在该窗口中可以对提交记录拖拽更改提交顺序,以及删除某个不想要的提交。
3、 本地栈式提交
来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。
这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!
最后就差把 bugFix 分支里的工作合并回 main 分支了。你可以选择通过 fast-forward
快速合并到 main 分支上,但这样的话 main 分支就会包含我这些调试语句了。你肯定不想这样,应该还有更好的方式……
实际我们只要让 Git 复制解决问题的那一个提交记录就可以了。跟之前我们在“整理提交记录”中学到的一样,我们可以使用
# 打开一个UI界面,将在UI页面中进行的操作复制到想要复制的节点下
git rebase -i <想要复制到的节点/分支>
# 复制想要的提交到HEAD下
git cherry-pick <提交号>...
# 比如
git cherry-pick c1 c2
来达到目的。
cherry-pick
可以将提交树上的任何地方的提交记录提取过来追加到 HEAD 上(只要不是 HEAD 上游的提交就没问题)
4、git tag
相信通过前面课程的学习你已经发现了:分支很容易被人为移动,并且当有新的提交时,它也会移动。分支很容易被改变,大部分分支还只是临时的,并且还一直在变。
你可能会问了:有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢?
当然有了!Git 的 tag 就是干这个用的啊,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。
更难得的是,它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。
创建标签:
git tag V1 C1 # 建立一个标签,指向提交记录 C1,表示这是我们 1.0 版本
5、 Git Ddescribe
由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe
!
Git Describe
能帮你在提交历史中移动了多次以后找到方向;
git describe
的语法是:
git describe <ref>
<ref>
可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会使用你目前所在的位置(HEAD)。
它输出的结果是这样的:
<tag>_<numCommits>_g<hash>
tag
表示的是离 ref
最近的标签, numCommits
是表示这个 ref
与 tag
相差有多少个提交记录, hash
表示的是你所给定的 ref
所表示的提交记录哈希值的前几位。
当 ref
提交记录上有某个标签时,则只输出标签名称
6、多分支合并(rebase)
让我们把所有这些分支上所做的工作都通过rebase合并到main分支上吧。但是你的领导给你提了点要求一他们希望得到有序的提交历史,也就是我们最终的结果应该是C6’在C?上面,C5′在C6上面,依此类推。
git rebase main bugFix
git rebase bugFix side
git rebase side another
git rebase another main
7、选择 parent 提交记录
示例1:
git checkout main^
git checkout main^2
示例2:
上图的操作符还支持链式操作,以上的3条指令可以用下面1条指令替代:
git checkout HEAD~^2~2
示例3:
要求:在提交树的某个节点创建新的分支
实现方式:
git branch bugWork main^^2~
四、远程仓库
1、远程仓库的命名规范
<remote name>/<branch name>
2、git fetch:从远程仓库获取数据
先来看一下示例:
3、git pull
4、push
示例1:
历史偏离
示例:
如何解决上述问题呢?可以使用git rebase
或者使用 git merge
或者直接使用git pull --rebase