git commit
git checkout -b bugFix
开始的效果
操作后的效果
git checkout -b bugFix
git commit
git checkout main
git commit
git merge bugFix
没有操作前
操作后
git checkout -b bugFix
git commit
git checkout main
git commit
git checkout bugFix
git rebase main
开始的图解
结束以后的图解
git checkout C4
开始的图
操作以后的图片
git checkout bugFix
git checkout HEAD~1
操作开始时候的图片
操作以后的结果图片
git checkout bugFix
git branck -f bugFix C0
git branck -f main C6
git checkout C1
reset图解
revert图解(对于reset就是多出来一个版本信息)
例子
最后想要得到的结果
git reset HEAD~1
git checkout pushed
git revert HEAD
例子
git cherry-pick C2 C4 (这里就是合并了c2和c4的变更)
例子
git rebase -i HEAD~4 (选中4个开始可以动态的操作节点)
作业
结果
git rebase -i HEAD~4
开始图片
操作结束以后
git branch -f main caption
git rebase -i HEAD~2 (操作交换位置)
git commit --amend (小修改)
git rebase -i HEAD~2 (交换位置得到结果)
操作数据前
操作以后
git tag v1 C1
由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是
git describe
!Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用
git bisect
(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令
例子
git tag v2 C3
git describe main
会输出:
v1_2_gC2
git describe side
会输出:
v2_1_gC4
开始前
操作以后
git branck -f bugWork C2
你可能想问这些远程分支的前面的
o/
是什么意思呢?好吧, 远程分支有一个命名规范 —— 它们的格式是:
/ 因此,如果你看到一个名为
o/main
的分支,那么这个分支就叫main
,远程仓库的名称就是o
。大多数的开发人员会将它们主要的远程仓库命名为
origin
,并不是o
。这是因为当你用git clone
某个仓库时,Git 已经帮你把远程仓库的名称设置为origin
了不过
origin
对于我们的 UI 来说太长了,因此不得不使用简写o
:) 但是要记住, 当你使用真正的 Git 时, 你的远程仓库默认为origin
!说了这么多,让我们看看实例。
开始操作前
操作以后
正如你所见,Git 变成了分离 HEAD 状态,当添加新的提交时
o/main
也不会更新。这是因为o/main
只有在远程仓库中相应的分支更新了以后才会更新。
例子
git fetch操作以后
git fetch 做了些什么
git fetch
完成了仅有的但是很重要的两步:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如
o/main
)
git fetch
实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。如果你还记得上一节课程中我们说过的,远程分支反映了远程仓库在你最后一次与它通信时的状态,
git fetch
就是你与远程仓库通信的方式了!希望我说的够明白了,你已经了解git fetch
与远程分支之间的关系了吧。git fetch 不会做的事
git fetch
并不会改变你本地仓库的状态。它不会更新你的main
分支,也不会修改你磁盘上的文件。理解这一点很重要,因为许多开发人员误以为执行了
git fetch
以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。我们在后面的课程中将会讲解能完成该操作的
既然我们已经知道了如何用
git fetch
获取远程的数据, 现在我们学习如何将这些变化更新到我们的工作当中。其实有很多方法的 —— 当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说就是你可以执行以下命令:
git cherry-pick o/main
git rebase o/main
git merge o/main
- 等等
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要讲的
git pull
开始操作前
git fetch;git merge o/main
git pull的效果
开始操作前
操作以后
同样的结果!这清楚地说明了
git pull
就是 git fetch 和 git merge 的缩写!
上传自己分享内容与下载他人的分享刚好相反,那与
git pull
相反的命令是什么呢?git push
!
git push
负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。一旦git push
完成, 你的朋友们就可以从这个远程仓库下载你分享的成果了!你可以将
git push
想象成发布你成果的命令。它有许多应用技巧,稍后我们会了解到,但是咱们还是先从基础的开始吧……注意 ——
git push
不带任何参数时的行为与 Git 的一个名为push.default
的配置有关。它的默认值取决于你正使用的 Git 的版本
操作前
操作以后
git push
git fakeTeamwork foo 3 表示远程提交3次
开始操作前
操作以后
git clone
git fakeTeamwork 2 (远程提交2次)
git fetch (远程分支拉去)
git commit (本地提交一次)
git merge o/main (合并远程分支)
git push
看见了吧?什么都没有变,因为命令失败了!
git push
失败是因为你最新提交的C3
基于远程分支中的C1
。而远程仓库中该分支已经更新到C2
了,所以 Git 拒绝了你的推送请求。
处理办法
效果
我们用
git fetch
更新了本地仓库中的远程分支,然后用 rebase 将我们的工作移动到最新的提交记录下,最后再用git push
推送到远程仓库。
使用merge替换rebase
我们用
git fetch
更新了本地仓库中的远程分支,然后合并了新变更到我们的本地分支(为了包含远程仓库的变更),最后我们用git push
把工作推送到远程仓库
当然 —— 前面已经介绍过
git pull
就是 fetch 和 merge 的简写,类似的git pull --rebase
就是 fetch 和 rebase 的简写!
新创建一个分支,然后切换到被拒绝的分支进行reset HEAD操作,保持出现问题的分支和原来的是一致的,然后先执行pull操作,然后再执行push操作就可以解决问题了
git checkout -b totallyNotMain o/main
就可以创建一个名为
totallyNotMain
的分支,它跟踪远程分支o/main
。
开始操作前
git checkout -b foo o/main ;git pull
正如你所看到的, 我们使用了隐含的目标
o/main
来更新foo
分支。需要注意的是 main 并未被更新!
第二种方法
另一种设置远程追踪分支的方法就是使用:
git branch -u
命令,执行:
git branch -u o/main foo
这样
foo
就会跟踪o/main
了。如果当前就在 foo 分支上, 还可以省略 foo:
git branch -u o/main
git push
git push origin main
把这个命令翻译过来就是:
切到本地仓库中的“main”分支,获取所有的提交,再到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去,搞定之后告诉我。
例子
操作前
git checkout C0; git push origin main (这个命令就是可以指定提交那个分支)
如果执行 git checkout C0;git push
命令失败了(正如你看到的,什么也没有发生)! 因为我们所检出的 HEAD 没有跟踪任何分支。
要同时为源和目的地指定
的话,只需要用冒号
:
将二者连起来就可以了:
git push origin
例子
git push origin foo^:main
操作以后的效果
git push origin main:newBranch
使用前
git fetch origin foo
git fetch origin foo~1:bar
效果
Git 有两种关于
的用法是比较诡异的,即你可以在 git push 或 git fetch 时不指定任何
source
,方法就是仅保留冒号和 destination 部分,source 部分留空。
git push origin :side
git fetch origin :bugFix
效果
git push origin :foo
就是这样子, 我们通过给 push 传空值 source,成功删除了远程仓库中的
foo
分支, 这真有意思...
如果 fetch 空 到本地,会在本地创建一个新分支。
git fetch origin :bar
以下命令在 Git 中是等效的:
git pull origin foo
相当于:
git fetch origin foo; git merge o/foo
还有...
git pull origin bar~1:bugFix
相当于:
git fetch origin bar~1:bugFix; git merge bugFix
看到了? git pull 实际上就是 fetch + merge 的缩写, git pull 唯一关注的是提交最终合并到哪里(也就是为 git fetch 所提供的 destination 参数)
初始化(右边是远程仓库,左边是本地仓库)
操作
git fetch origin bar:foo
git fetch origin main:side
git merge C3
git merge C2