练习地址:https://learngitbranching.js.org/?locale=zh_CN
核心
基础篇章
git commit
- git checkout <分支名> 分支切换
git branch
- git branch 创建分支
- git checkout -b <新分支名> 创建分支并切换当前分支
git merge
-
// 新建一个bugFix分支,然后提交数据,然后切换到main分支,提交数据, 最后吧bugFix的代码合并到main。使main成为代码是最新 git checkout -b bugFix (git branch bugFix;git checkout bugFix) git commit git checkout main git commit git merge bugFix
git rebase
-
// 新建一个bugFix分支,然后提交数据,然后切换到mian分支,提交数据,然后切换到bugFix分支,使用用rebase拉到main分支新的提交 git checkout -b bugFix git commit git checkuot main git commit git chekcout bugFix git rebase main
高级篇
分离 HEAD
- HEAD 可以指向分支名,也可以指向commit哈希值
相对引用
-
操作符(
)、main
^
、HEAD
// 切换到bugFix分支的上一个提交记录 git checkout bugFix^
-
操作符(~)
// 切换到bugFIx分支的向上3步的提交记录 git checkout bugFix~3
强制移动分支
// 把HEAD 上移一步,把bugFix 强制移动到c0,把main强制移动到c6
git checkout HEAD^
git branch -f bugFix c0
git branch -f main c6
撤销变更
-
git reset :撤销本地提交
-
git revert:撤销远程提交
分别撤销 local 分支和 pushed 分支上的最近一次提交 local 本地分支,pushed 远程分支 git reset local git checkout pushed git revert pushed
整理提交记录
Git cherry-pick
// Git cherry-pick <提交号1> <提交号2>
// 当前分支main,整理bugFix分支的c3、side分支的c4、another分支的c7(知道hash值了)
git cherry-pick c3 c4 c7
交互式的rebase
// 交互式 rebase 指的是使用带参数 --interactive 的 rebase 命令, 简写为 -i
git rebase -i HEAD~n
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
以上操作完成后.需要强制提交-f。 也就是force
git push -f
杂项
本地栈式提交
确保
main
分支能得到
bugFix
分支上的相关提交。注意:bugFix有三个提交,c1-debug记录;c2-打印记录;c3-修改记录
-
git rebase -i
git rebase -i HEAD~3 (可以去选择只留下c3记录) git branch -f main c3' (git checkout mian; git)
-
git cherry-pick
git checkout main git cherry-pick c3
提交的技巧 #1
接下来这种情况也是很常见的:你之前在
newImage
分支上进行了一次提交,然后又基于它创建了
caption
分支,然后又提交了一次。此时你想对某个以前的提交记录进行一些小小的调整。比如设计师想修改一下
newImage
中图片的分辨率,尽管那个提交记录并不是最新的了。
-
使用rebase -i 切换掉提交顺序,把需要修改的commit 放入最前面 使用git commit --amend 追加提交记录 使用rebase -i 还原回原来顺序 使用git branch -f main caption 把mian分支切换到caption上
提交的技巧 #2
同 提交的技巧 #1。但是只能使用git cherry-pick
修改中间的分支,然后合并,少量几条记录用这个还可以,如果太多。建议用rebase
-
git checkout newImage git commit --amend git checkout main git cherry-pick c2'' c3
Git Tags
git tag <tag名称> <分支名或commitid;默认是HEAD>
Git describe
git describe <ref> (ref可以是提交记录,可以是分支名,不输入,默认是HEAD)
上面语法输出的结果:__g
:最近的tag
_g :ref提交记录最近的tag记录
: hash值
高级话题
多分支 rebase
直接合并多个分支,然后采用rebase -i 调整分支顺序即可。
两个父节点
操作符(^) 后面也可以加数字,但是并不是向上返回几代,而是选择指定提交记录的某个父提交。
-
git checkout main^ 检出父节点 git checkout main^^ 检查父父节点 git checkout mian^2 检出父节点第二个(可能当前mian分支有多个父节点)
-
操作符支持链式:
git checkout HEAD~^2~2
git branch -f bugWork HEAD~^2~ 快速在某个地点创建分支。
纠缠不清的分支
远程
远程仓库默认是origin。所以clone后的本地分支默认就是origin/master
Push & Pull —— Git 远程仓库!
git clone
git fetch
就是把本地分支中的远程分支更新成了远程仓库相应分支的最新状态
git pull
git pull 就是 git fetch + git merge xxx 的缩写
因为要拉取最新代码就要git fetch后用如下命令更新
git cherry-pick
git rebase 目标分支,把目标分支合并过来
git merge 目标分支。把目标分支合并过来
模拟团队合作
用pull 或fetch+merge
git push
git push
不带任何参数时的行为与 Git 的一个名为
push.default
的配置有关。它的默认值取决于你正使用的 Git 的版本,但是在教程中我们使用的是
upstream
。 这没什么太大的影响,但是在你的项目中进行推送之前,最好检查一下这个配置。
偏离的提交历史
当出现本地分支和远程分支代码提交记录偏移时的解决方式
方法一:一般都rebase 远程分支,解决冲突后提交
git fetch
git rebase o/main
git push
方法二:merge
git fetch;
git merge o/main
git push
方法三: git pull –rebase (就是fetch 和 rebase的简写)
git pull –rebase
git push
方法四: 直接用git pull
锁定的Main(Locked Main)
场景:当在本地master多次提交,然后最后push远端分支,发现错误,不能提交。时的处理方式
以上场景就是因为没有用PR流程导致:当master分支被锁定,就只能用PR (pull request) 来提交了
正常的是新建一个分支,然后push这个分支,并申请PR请求
修复场景:
注意记住当前修改的最后提交commitId
git reset <指定远端的分支节点>
git checkout -b <feature新分支> <之前的最后提交commitId>
git push
关于 origin 和它的周边 —— Git 远程仓库高级操作
推送主分支(rebase)
远端分支 o/mian 提交记录c8
本地远程分支main 提交记录c 1
本地分支 side1 提交记录 c2
本地分支 side2 提交记录 c3 c4
本地分支 side3 提交记录 c5 c6 c7(HEAD)
采用rebase
git rebase side2
git rebase side1
git branch -f main side3
git checkout master
git pull –rebase
git push
要求三个分支都同步远程分支,并且在一根线
. 采用cherry-pickgit checkout main
git pull –rebase
git cherry-pick c2 c3 c4 c5 c6 c7
git branch -f side1 c2’
git branch -f side2 c4’
git branch -f side3 c7’
git push
采用merge
git checkout main
git pull –rebase
git merge side1
git merge side2
git merge side3
git push
合并远程仓库(merge)
Merge 解决方法在上一条可见了
为什么有的人用merge,有的人用rebase
在开发社区里,有许多关于 merge 与 rebase 的讨论。以下是关于 rebase 的优缺点:
优点:
- Rebase 使你的提交树变得很干净, 所有的提交都在一条线上
缺点:
- Rebase 修改了提交树的历史
比如, 提交 C1 可以被 rebase 到 C3 之后。这看起来 C1 中的工作是在 C3 之后进行的,但实际上是在 C3 之前。
一些开发人员喜欢保留提交历史,因此更偏爱 merge。而其他人(比如我自己)可能更喜欢干净的提交树,于是偏爱 rebase。仁者见仁,智者见智。
远程跟踪-分支
检出一个名叫
foo
的新分支,让其跟踪远程仓库中的
main
第一种方法:git checkout -b <新分支> <远端分支:o/main>
当前所在foo,测试:git cmmit ; git push 。这时候会发现foo 关联上了o/main
第二种方法:
当前在foo: git branch -u o/main
当前不在foo:git branch -u o/main foo
Git push 的参数
语法:git push
解释:git push origin main
- 切换到本地的main分支,获取所有提交
- 再到远程仓库“origin” 找到“main”分支,将远程分支没有的提交记录都添加上去
我们是通过“place”来确定提交记录来自哪里,需要推送到远程仓库的哪个分支。
Git push 参数 2
如果来源和去向分支的名称不同呢?比如你想把本地的
foo
分支推送到远程仓库中的
bar
分支。哎,很遗憾 Git 做不到…… 开个玩笑,别当真!当然是可以的啦 😃 Git 拥有超强的灵活性(有点过于灵活了)
语法:git push origin : 可以写提交节点或链式哦
例如:git push origin foo^:main
Git fetch 的参数
语法:git fetch
解释:git fetch origin foo
- 到远程origin仓库的foo分支,获取所有本地不存在的提交
- 下载提交记录到本地的o/foo分支上
语法:git fetch origin : 可以写提交节点或链式哦
执行时destination分支不存在,会直接创建本地分支
例如1:git fetch origin o/main:o/foo
例如2:git fetch origin o/main:foo (注意这个会影响你本地的代码哦)
没有 source 的 source
语法1: git push origin :side
push 了空的到远端分支,那么也就是删除了远端分支side及本地分支side
语法2: git fetch origin :bugFix
fetch 空的下来本地bugFix分支,也就是创建一个分支
Git pull 的参数
就是fetch + merge的组合
语法:git pull
等价命令:git pull origin foo ===>>>> git fetch origin foo;git merge o/foo
语法:git pull origin : 可以写提交节点或链式哦
等价命令:git pull origin bar~1:bugFix ===>>>> git fetch origin bar~1:bugFix;git merge bugFix
如果destination不存在,也会创建分支的,然后pull的