学习网址:https://learngitbranching.js.org/?locale=zh_CN 可实际操作非常好,以下内容来自上面网址整理
基础篇
git commit: 提交记录可看作是本地项目的快照,提交记录非常的轻量,可以快速在提交记录之间切换 git branch:
- 只是简单的指向某个提交记录
- 建再多的分支也不会造成存储和内存上的开销,并且按照逻辑分解工作到各个分支更有益于维护。因而:早建分支!多建分支!
- 使用分支就相当于在说:“我想基于这个提交和它所有的父提交开展新的工作”
- 要在新分支上提交记录需要切换分支“get checkout <ref>”,在未来切换将会由“git switch”替代
- 简单写法“git check -b <your branch name>”,将创建一个新分支并切换到该分支
git merge:在git上合并两个分支(两个分支都要有各自新增的内容才可以),会产生一个特殊的提交记录,它有两个父节点,这条指令翻译成自然语言就是:“我要把这两个父节点和它们所有的的祖先都包含进来”,eg;main分支想要合并bugFix分支,先切换到main分支,然后执行git merge bugFix
git rebase:
- 另一种分支合并方式!取出一系列记录,“复制”它们然后在另一个地方逐个放下去
- 使用git rebase的好处是可以创造更好的线性提交历史,提交历史会更清晰。在执行 git rebase main 之后,bugFix分支中的工作添加到了main上,移动之后看上去C2和C3就好像是顺序开发的,但实际上是并行开发的.原始C3还在,移到main上的是原始C3的副本。图中一个分支是一个颜色,合并后的涅日共是混合后的颜色,当所有节点颜色相同,表示合并完成。
切换到main 分支执行git rebase bugFix,git将引用向前引用了一步
高级篇
分离HEAD
HEAD:指向你正在其基础上修改的记录(当前检出记录),大多数修改提交树的GIT命令都是从改变HEAD的指向开始的,HEAD的指向跟着提交记录变; 分离的HEAD:分离的HEAD就是让其指向了某个具体的提交记录而不是分支名。 当一条git命令执行之前;HEAD指向mian, main指向C1; 当执行了 git checkout C1 之后,HEAD指向C1(这里C1代表哈希值,通过哈希值指定提交记录)
相对引用
- 实际用时通过
git log 查看提交记录哈希值 - 真实GIT世界中哈希值更长(基于SHA-1,共40位)。但GIT不需要全部输入完整哈希值,只要输入能标识提交记录的几个字符就可以。
- 相对引用使得你可以从一个容易记忆的地方(如bugFix或HEAD)开始计算。
(1) ^ 表示向上移动1个提交记录,eg1: git checkout main^ 。 eg2:git checkout main^^ 表示连续向上提交1个记录即两个记录。 eg3: git checkout C3;git checkout HEAD^; git checkout HEAD^; 可以一直向上移动 (2)~<num> 表示向上移动多个提交记录,eg: git checkout HEAD~4 。不跟数字的时候就是默认向上一次
分支强制引用
将branch强制引用到某个提交记录 eg: git branch -f main HEAD~3 将main分支移动到倒退三个提交的位置
撤销变更
方法一git reset
通过把分支回退到几个提交记录来实现撤销改动,类似“改写历史”。git reset 向上移动分支,原来指向的提交记录就像从来没有提交过一样(其实还在)。eg:git reset HEAD~1 方法二git revert
在自己的本地分支使用git reset 很方便,但是这种方法对大家一起使用的远程分支是无效的。 为了将撤销更改并分享给别人,需要使用git revert 。eg: git revert pushed/HEAD
以上操作涵盖git操作的90%
整理提交记录
当知道提交哈希值的时候 将一些提交复制到当前所在的位置(HEAD)下面的话,cherry-pick是最直接的方式,它可以将任何不是HEAD上游的提交记录取过来,追加到当前的HEAD上 以下是执行git cherry-pick C2 C4 示意图 执行前 执行后
交互式的rebase 选定一组提交记录,对这组提交记录进行重排或删除,eg:git rebase -i HEAD~4
杂项
本地栈式提交 只取一个提交记录合并到main,其它提交中的内容(调试、打印语句不取) eg: git cherry-pick <ref...> 想要修改旧的提交内容-1
- 先用
git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前 - 然后用 git commit --amend 来进行一些小修改
- 接着再用 git rebase -i 来将他们调回原来的顺序
- 最后把main 移到修改的最前端
想要修改旧的提交内容-2 上面的方法rebase排了两次序,并且有可能会因为rebase导致冲突,方法2是使用git cherry-pick <ref...>
- 调整HEAD到希望添加提交的记录
git checkout <ref> - 执行
git commit --amend - 执行
git cherry-pick <ref...>
git tag 分支的名字是分支的名字,不是某条记录的,是一连串记录的名字,是动态可变的(从上面的学习可以验证到)。Tag是永远指向某个提交记录的特定标识(亦可称之为锚点),标记好后,不会随着分支的延展而移动。可以用来标记版本信息、新特性等等需要标记的地方。标记后可以像分支那样被引用,可以切换到该版本上。 指令:git tag V1 C1 C1为某条提交记录,如果没有C1那么将默认把tag标记到HEAD上
git describe 用以描述离你最近的锚点,让你了解当前项目的进度。 指令:git describe <ref> ref 表示任何可以被GIT识别成提交记录的引用, 返回结果的结构: <tag>_<numCommits>_g<hash> tag 表示是离ref 最近的tag ,numCommits 表示这个ref 与tag 相差有多少个提交记录,hash表示的是你所给定的ref所表示的提交记录哈希值的前几位,当给定的ref 提交记录上有某个标签值得时候,则只输出标签名称
git bisect 一个查找产生Bug的提交记录的指令
选择父提交记录 合并提交的时候,有两个父提交,遇到这样的节点怎么确定哪个节点,不是很清晰,使用^num 标记是哪个父节点,eg:git checkout HEAD~ ; 使用^ 或~ 可以在提交树上游走~,并且支持链式操作。eg: git checkout HEAD~^2~2
远程仓库
远程仓库只是你的仓库在另一台计算机上的拷贝,可以通过因特网与这台计算机通信——也就是增加或是提交记录。远程仓库的特性:
- 远程仓库是一个强大的备份。本地仓库也有恢复到指定版本的能力,但所有的信息都是保存在本地的。有了远程之后,即使本地丢了也可以通过远程仓库拿回丢失的数据。
- 远程让代码社交化了!既然项目被托管到别的地方了,你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)
git clone——在本地创建一个远程仓库的拷贝 远程分支 在执行git clone 之后本地仓库多了一个名为o/main 的分支,这类分支叫做远程分支。 远程分支反映了(在你上次和它通信时)的状态。心中要揣着这一点,这有助于你理解本地工作与公共工作的差别——这是你与别人分享工作成果前至关重要的一步。 远程分支有一个特别的属性,在你检出时自动进入分离HEAD状态.git这么做是出于不能直接在这些分支上进行操作的原因,你必须在别的地方完成你的工作,(更新了远程分支之后)再用远程分享你的工作成果。 为什么有o/ 远程分支有一个命名规范——它们的格式是:<remote name>/<branch name> 因此名为o/main 的分支,那么这个分支就叫main ,远程仓库的名称就是o 。 大多数开发人员将他们主要的远程仓库命名为orgin ,并不是o ,这是因为当你用git clone 某个仓库的时,git已经帮你把远程仓库的名称设置为origin 了。 在本地分支提交记录,如下图:git checkout o/main;git commit git fetch GIT远程仓库主要操作可以归结为两点:向远程仓库传输数据以及从远程仓库获取数据。既然我们能与远程仓库同步,那么就可以分享任何能被GIT管理的更新(代码、文件、想法等) git fetch :从远程仓库获取数据,使用该命令后远程分支也会更新以反映最新的远程仓库。 git fetch 要说的几点:
- 它从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如
o/main )到最新提交记录 git clone 是与远程仓库的第一次通信,git fetch 是后来与远程仓库通信的方式git fetch 通常通过互联网(使用http:// 或git:// 协议)与远程仓库通信git fetch 并不会改变你本地仓库的状态。它不会更新你的main 分支,也不会修改你磁盘上的文件。理解这一点很重要,因为许多开发人员误以为执行了git fetch 以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需要的数据都下载了下来,但是并没有修改你本地的文件。可以将git fetch 单纯的理解为下载操作。
git pull 抓取更新再合并到本地分支 执行:git fetch: git merge o/main 执行前 执行后 fetch操作下载了C3,然后通过git merge o/main 合并了这一提交记录。现在main分支包含了远程仓库中的更新 git pull 就是git fetch 和 git merge 的缩写!
git pull --rebase 等价于fetch + rebase
**git push ** 将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交的记录。git push 不带任何参数时的行为与GIT的一个名为push default 的配置有关,默认值取决于正在使用的GIT版本。在项目推送之前,最好检查一下这个配置。 git push <remote> <place> eg: git push orginal main :切到本地仓库中的“main”分支,获取所有的提交,再到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去,搞定之后告诉我。需要注意的是,因为我们通过指定参数告诉了 Git 所有它需要的信息, 所以它就忽略了我们所检出的分支的属性!
远程服务器拒绝!(Remote Rejected) 如果你是在一个大的合作团队工作,很可能main被锁定了,需要一些pull Request流程来合并修改。如果直接提交到本地main,然后试图推送修改,将会看到这样的信息: ! [远程服务器拒绝] main -> main (TF402455: 不允许推送(push)这个分支; 你必须使用pull request来更新这个分支. 为什么会被拒绝? 因为配置原因,你应该按照流程,新建一个分支, 推送(push)这个分支并申请pull request,但是你忘记并直接提交给了main.现在你卡住并且无法推送你的更新. 解决办法 新建一个分支feature, 推送到远程服务器. 然后reset你的main分支和远程服务器保持一致, 否则下次你pull并且他人的提交和你冲突的时候就会有问题.
|