一.分支
git branch
现在只要记住使用分支其实就相当于在说:“我想基于这个提交以及它所有的父提交进行新的工作。”
新建一个newImage分支,指向当前的c1节点(提交记录),*号表示当前所在的分支
如果此时我git commit,增加一个提交记录,则main分支会往前,而newImage分支不会,因为当前分支在main上。
如果我们切换分支git checkout newImage
然后再git commit
,这样子我们的修改就保存在新分支上面了
git checkout -b bugFix
创建分支并切换过去
二.合并分支
在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个父节点。相当于:“我要把这两个父节点本身及它们所有的祖先都包含进来。”(上面的是父亲)
方法一
使用git merge
场景
我们有两个不同的分支,每个分支上各有一个独有的提交。但是没有一个分支包含了我们所有的修改。所以我们想把 bugFix 合并到 main 里
- 在main分支里
git merge bugFix
现在,main 指向了一个拥有两个父节点的提交记录。假如从 main 开始沿着箭头向上看,在到达起点的路上会经过所有的提交记录。这意味着 main 包含了对代码库的所有修改。 - 把main分支合并到bugFix分支
git checkout bugFix
git merge main
由于main分支继承自bugFix分支,所以只需要把 bugFix 移动到 main 所指向的那个提交记录。
方法二
第二种合并分支的方法是 git rebase
。
- rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
- rebase 的优势就是可以创造更线性的提交历史
git rebase side1 side2
:把side2放在side1后面
场景
我们想要把bugFix分支里的内容直接移到main分支上面
git rebase main
注意:提交记录 C3 依然存在(树上那个半透明的节点),而 C3’ 是我们 Rebase 到 main 分支上的 C3 的副本。
此时main还没有更新
git checkout main
git rebase bugFix
由于 bugFix 继承自 main,所以 Git 只是简单的把 main 分支的引用向前移动了一下而已。
三.HEAD
HEAD 总是指向当前分支上最近一次提交记录(指向分支)。
- 如果想让HEAD指向提交记录的节点的话,就需要通过哈希值指定提交记录。然后通过
git checkout 哈希值
就可以成功将head指向该提交记录。 git log
来查看提交记录的哈希值。
由于使用哈希值比较麻烦,所以git引入了相对引用
- main^表示main的父节点
- main^^表示 main 的第二个父节点
git checkout main^
如图所示。
当然,我们也可以将 HEAD 作为相对引用的参照。
我们也可以通过git checkout HEAD~4
(相对引用)
四.强制修改分支位置
git branch -f main HEAD~1
把main分支强制移动到head的第一个父节点
五.撤销
git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset HEAD~1
六.远程仓库
git clone
:在本地创建一个远程仓库的拷贝。- 本地仓库中会有远程分支,如oringin/master,它对应远程仓库中的master分支。
- 远程分支有一个命名规范 —— 它们的格式是:
<remote name>/<branch name>
(当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了。) git checkout o/main
git commit
Git 变成了分离 HEAD 状态,当添加新的提交时 o/main 也不会更新。这是因为 o/main 只有在远程仓库中相应的分支更新了以后才会更新。
Git 远程仓库的操作可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据
获取数据
git fetch
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如 o/main)
git fetch之后本地仓库的远程分支就更新成了远程仓库相应分支最新的状态。 - 它不会更新本地仓库的main分支,只是完成一个下载远程仓库的操作
场景
这里我们有一个远程仓库(右边), 它有两个我们本地仓库(左边)中没有的提交。
执行git fetch
之后
由上图可见,C3 被下载到了本地仓库,同时远程分支 o/main 也被更新。
由于它不会更新本地仓库的main分支,只是完成一个下载远程仓库的操作。所以我们想要把这些变化更新到本地。就引入了git pull
git pull
先抓取更新再合并到本地分支 = git fetch
下载远程仓库的东西 +git merge o/main
合并远程分支到本地main分支上
传输数据
git push
(后面的团队合作有例子)
git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。
七.模拟团队合作
- 左边是本地仓库,右边是远程仓库。
本地仓库是c4和c5提交,远程仓库是你的同学所做的提交。 - 如果直接执行
git push
,会无效。
- 由于历史偏离有许多的不确定性,Git是不会允许你 push 变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。
- 我们先执行
git fetch
把同学的修改下载下来,变成了下图。
- 然后执行
git rebase o/main
,将我们的工作移动到最新的提交记录下。
当然,第四步的rebase也可以用merge,merge之后长这样。
git push
推送到远程仓库上
当然,这五个步骤可以省略成git pull --rebase
和git push
。
或者是git pull
(git fetch
+git merge
)和git push
八.远程追踪
git checkout -b totallyNotMain o/main
可以创建一个名为 totallyNotMain 的分支,它跟踪远程分支 o/main
九.git push的参数
git push <remote> <place>
git push origin main
表示把本地仓库的main分支推送到远程仓库的main分支上,保持两个仓库的一致性。这里的main同时指定了本地和远程的目的。git push origin <source>:<destination>
这个可以指定独立的来源和目的地。