GIT学习笔记

学习资料

本地

git commit

一个新提交。

git branch

创建一个新分支。

Git 的分支也非常轻量。

sh 复制代码
git branch newImage

创建新分支。接下来继续切换分支

sh 复制代码
git checkout newImage

注意:在 Git 2.23 版本中,引入了一个名为 git switch 的新命令,最终会取代 git checkout,因为 checkout 作为单个命令有点超载(它承载了很多独立的功能)。 由于现在很多人还无法使用 switch,本次课程仍然使用 checkout 而不是 switch, 但是如果你想尝试一下新命令,我们的应用也是支持的!并且你可以从这里学到更多关于新命令的内容。

如果你想创建一个新的分支同时切换到新创建的分支的话 git checkout -b <your-branch-name> 来实现

sh 复制代码
git checkout -b newImage
等于
git branch newImage
git checkout newImage

git merge

合并两个分支: Git 中合并两个分支时会产生一个特殊的提交记录,它有两个 parent 节点。翻译成自然语言相当于:"我要把这两个 parent 节点本身及它们所有的祖先都包含进来。"

这里可以看到。带星号的分支。去合并merge后面的分支

这里值得注意。main继承自其他的分支,其他分支再去合并main的时候,并不会产生新的节点,而是指向合并的那个提交记录。

题目

sh 复制代码
git checkout -b bugFix
git commit
git checkout main
git commit
git merge

git rebase

合并分支的方法是 git rebase实际上就是取出一系列的提交记录,"复制"它们,然后在另外一个地方逐个的放下去。

这个方法可以理解成重新设置根据地。这里就是把bugFix写到main的下一个节点。

再切换到main执行git rebase bugFix,效果只是把main分支引用向前移动

题目:

sh 复制代码
git checkout -b bugFix
git commit
git checkout main
git commit
git checkout bugFix
git rebase main

HEAD是是当前所在分支的符号引用。

  • 如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看
  • 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向。

分离的HEAD:正常的HEAD指向的是所在的分支名。分离的HEAD是让它指向某一个具体的提交记录。

正常情况下是这样的

sh 复制代码
HEAD -> main -> C1
HEAD 指向 main, main 指向 C1

git checkout c1   这里checkout操作的是HEAD

git checkout c1分离之后的是这样的

sh 复制代码
HEAD -> C1

题目:

sh 复制代码
git checkout c4

git checkout

移动提交记录的两种方法:

  • git checkout :移动的是HEAD
  • git branch -f :移动的是分支

上面例子中的c2,c3,c4其实都是提交记录的哈希值,查看的命令是git log

在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用 git log 来查查看提交记录的哈希值。

并且哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)。例如前一关的介绍中的提交记录的哈希值可能是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌头都快打结了吧...比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。

通过哈希值指定这个提交记录不是很方便。所以有相对引用。相对引用的对象可以是HEAD,引用名称。

  • 使用 ^ 向上移动 1 个提交记录
  • 使用 ~<num> 向上移动多个提交记录,如 ~3

题目:

sh 复制代码
git checkout bugFix~

值得注意。 checkout操作的作用是切换当前的操作分支。也就是head

git branch -f

使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

sh 复制代码
git branch -f main HEAD~3

上面的命令会将 main 分支强制指向 HEAD 的第 3 级 parent 提交。

题目:

sh 复制代码
git branch -f main c6
git checkout HEAD~
git branch -f bugFix HEAD~

这个题目很好的反应了。如果想移动HEAD的节点用``checkout就可以完成。checkout的操作的对象就是HEAD。如果想移动其他的分支那就用git branch -f`。

撤销变更

主要有两种方法用来撤销变更 ------ 一是 git reset,还有就是 git revert。接下来咱们逐个进行讲解。

  • git reset:撤销本地的分支, 这个命令就可以看成移动所在分支到某个位置
    功能与移动分支有点像------------git branch -f
    git checkout HEAD~这个移动HEAD到某个位置
  • git revert:增加一个新提交,这个新提交跟上上一个提交内容一样,可以给远程的使用

题目:

sh 复制代码
git reset HEAD~   这个命令就可以看成移动所在分支到某个位置
					功能与移动分支有点像,git branch -f
					git checkout HEAD~这个移动HEAD到某个位置
					
git checkout pushed
git revert HEAD

Git Cherry-pick

git cherry-pick, 命令形式为:

  • git cherry-pick <提交号>...

作用:简而言之在HEAD下面复制一些之前的提交。

如果你想将一些提交复制到当前所在的位置(HEAD)下面的话, Cherry-pick 是最直接的方式了。

题目

sh 复制代码
git cherry-pick bugFix side~ another
或者
git cherry-pick c3 c4 c7

交互式的 rebase

rebase就是重新选择base加上-i代表交互式,以哪个提交为base呢,就看最后一个参数HEAD~n

当你知道你所需要的提交记录(并且 还知道这些提交记录的哈希值)时 cherry-pick 再好不过了

但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase

交互式 rebase 指的是使用带参数 --interactiverebase 命令, 简写为 -i

题目:

sh 复制代码
git rebase -i HEAD~4

本地栈式提交

来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。

这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!

最后就差把 bugFix 分支里的工作合并回 main 分支了。你可以选择通过 fast-forward 快速合并到 main 分支上,但这样的话 main 分支就会包含我这些调试语句了。你肯定不想这样,应该还有更好的方式......

sh 复制代码
方式1
git checkout main
git cherry-pick bugFix
这里也可以看着使用cherry-pick,需要把HEAD移动到要操作的节点
方式2
git rebase -i HEAD~3
git branch -f main bugFix   这里注意:*应该还在bugFix上面

提交的技巧 #1

你之前在 newImage 分支上进行了一次提交,然后又基于它创建了 caption 分支,然后又提交了一次。

此时你想对某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。

简而言之,想修改之前的提交

我们可以通过下面的方法来克服困难:

  • 先用 git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前
  • 然后用 git commit --amend 来进行一些小修改
  • 接着再用 git rebase -i 来将他们调回原来的顺序
  • 最后我们把 main 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!
sh 复制代码
git rebase -i HEAD~2
git commit --amend       这里注意HEAD在C2'上面,执行这个--amend,在这个位置再出现一个平行提交C2''
git rebase -i HEAD~2
git branch -f main caption

Git Tags

打标签:版本号;可以永远指向某个提交记录的标识呢,比如软件发布新的大版本

sh 复制代码
git tag v1 c1    我们将这个标签命名为 v1,并且明确地让它指向提交记录 C1,
git tag v1 			如果你不指定提交记录,Git 会用 HEAD 所指向的位置。
sh 复制代码
git tag v0 c1
git tag v1 c2
git checkout HEAD^1

Git Describe

作用:返回提交记录的标签和描述信息

git describe 的语法是:

sh 复制代码
git describe <ref>  < ref>可以是任何能被 Git 识别成提交记录的引用
git describe         Git 会使用你目前所在的位置(`HEAD`)

它输出的结果是这样的:

sh 复制代码
<tag>_<numCommits>_g<hash>

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 reftag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。

ref 提交记录上有某个标签时,则只输出标签名称

多次rebase

这一节是综合练习题:

sh 复制代码
git cherry-pick c3 c4 c5 c6 c7
本关不允许使用

这里还比较好理解:把bugfix重新设置basemain

这里一下子来了好几个,把sidebase设置成bugfix:可以理解成要复制成一个提交节点,需要把不同分支下的每一步修改都加上去。

sh 复制代码
git rebase main bugFix
git rebase bugFix side
git rebase side another
git rebase another main  这里是使用rebase改变main的位置

选择 parent 提交记录

  • 就是指间接引用时有两个parent的时候通过^选择不同的支路
  • 还有快捷方式,把^和~组合到一起
sh 复制代码
git branch bugWork HEAD~^2~

纠缠不清的分支

现在我们的 main 分支是比 onetwothree 要多几个提交。出于某种原因,我们需要把 main 分支上最近的几次提交做不同的调整后,分别添加到各个的分支上。
one 需要重新排序并删除 C5two 仅需要重排排序,而 three 只需要提交一次。

sh 复制代码
git checkout one
git cherry-pick c4 c3 c2
git checkout two
git cherry-pick c5 c4 c3 c2
git branch -f three c2

远程

引言:远程仓库并不复杂, 在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西, 但实际上它们只是你的仓库在另个一台计算机上的拷贝。你可以通过因特网与这台计算机通信 ------ 也就是增加或是获取提交记录

话虽如此, 远程仓库却有一系列强大的特性

  • 首先也是最重要的的点, 远程仓库是一个强大的备份。本地仓库也有恢复文件到指定版本的能力, 但所有的信息都是保存在本地的。有了远程仓库以后,即使丢失了本地所有数据, 你仍可以通过远程仓库拿回你丢失的数据。
  • 还有就是, 远程让代码社交化了! 既然你的项目被托管到别的地方了, 你的朋友可以更容易地为你的项目做贡献(或者拉取最新的变更)

现在用网站来对远程仓库进行可视化操作变得越发流行了(像 GitHub), 但远程仓库永远是这些工具的顶梁柱, 因此理解其概念非常的重要!

git clone

本地创建一个远程仓库的拷贝(比如从 github.com

在我们的本地仓库多了一个名为 o/main 的分支, 这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性。

  1. 远程分支有一个特别的属性,在你切换到远程分支时,自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果。

  2. 远程分支有一个命名规范 ------ 它们的格式是:

    <remote name>/<branch name>------------远程仓库名/分支名

    远程仓库名默认是 origin :因为当 git clone 某个仓库时,Git把远程仓库的名称设置为 origin

    因此,如果你看到一个名为 o/main 的分支,那么这个分支就叫 main,远程仓库的名称就是 o

    大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin

    不过 origin 对于我们的 UI 来说太长了,因此不得不使用简写 o 😃 但是要记住, 当你使用真正的 Git 时, 你的远程仓库默认为 origin!

本地切换远程分支:o/main 不会的改变,HEAD改变,分离了。

题目:

sh 复制代码
git commit
git checkout o/main  这里进入HEAD分离状态
git commit

git fetch

Git 远程仓库相当的操作实际可以归纳为两点:向远程仓库传输数据以及从远程仓库获取数据。

从远程仓库获取数据 ------ git fetch

git fetch 完成了仅有的但是很重要的两步:

  • 从远程仓库下载本地仓库中缺失的提交记录
  • 更新远程分支指针(如 o/main)

git fetch 实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态。

题目:

sh 复制代码
git fetch	

git Pull

git fetch 获取远程的数据, 现在需要把远程的数据和本地数据进行合并。

其实有很多方法的

  • git cherry-pick o/main
  • git rebase o/main
  • git merge o/main
  • 等等

实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要讲的 git pull

首先用 git fetch命令和git merge 命令:这个merge主要是以两个原来的为父节点生成一个新的节点。

git pull就是 git fetch 和 git merge 的缩写!

题目:

sh 复制代码
git pull

git push

上负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。

困难来自于远程库提交历史的偏离。在讨论这个问题的细节前,我们先来看一个例子......

本地修改了。远程仓库中该分支也更新了。也就是说本地这个修改之后的节点他的父节点在远程仓库中已经又更新了一个新节点。这个时候git就不知道把本地这个节点放在哪个位置了。

那该如何解决这个问题呢?

首先 rebase

类似的 git pull --rebase 就是 fetchrebase 的简写!

首先把远程仓库的节点给更新下来。再把我们的新更新的节点放在远程节点的下面。最后再给推送到远程仓库。

或者merge

这个就跟pull方法是一样的。不先把远程仓库给下载下来。然后再跟本地更新好的新节点。进行合并形成一个最新节点,然后push到远程的仓库。

当然 ------ 前面已经介绍过 git pull 就是 fetchmerge 的简写

题目:

sh 复制代码
git clone
git fakeTeamwork
git commit
git pull --rebase
git push

远程服务器拒绝!(Remote Rejected)

如果你是在一个大的合作团队中工作, 很可能是main被锁定了, 需要一些Pull Request流程来合并修改。如果你直接提交(commit)到本地main, 然后试图推送(push)修改, 你将会收到这样类似的信息:

sh 复制代码
! [远程服务器拒绝] main -> main (TF402455: 不允许推送(push)这个分支; 你必须使用pull request来更新这个分支.)

为什么会被拒绝?

  • 远程服务器拒绝直接推送(push)提交到main, 因为策略配置要求 pull requests 来提交更新.

  • 这里直接把本地仓库得main提交到远程仓库的main。显然这是不符合流程的。正确流程是先建立一个分支。然后去push这个分支,并申请Pull Request

解决办法:

  • 新建一个分支feature, 推送到远程服务器.
  • 然后reset你的main分支和远程服务器保持一致 , 否则下次你pull并且他人的提交和你冲突的时候就会有问题.

题目:

sh 复制代码
git reset o/main
或者
将main分支强制转到o/main
git branch -f main o/main
git checkout -b feature c2
git push origin feature
相关推荐
Funing726 分钟前
FreeRTOS学习day1:Keil 工程配置与 FreeRTOS 链表机制理解
数据结构·学习·链表
心中有国也有家38 分钟前
使用 DevEco Studio 配置 Flutter 鸿蒙签名
学习·flutter·华为·harmonyos
灯澜忆梦42 分钟前
MySQL 完整学习路线
学习·mysql
番茄育学园1 小时前
我的三款主流云存储音乐库实测笔记
笔记·分类·媒体
霸道流氓气质1 小时前
CodeBuddy中使用 MCP 工具将 XMind 思维导图转换为 Markdown —— 实操流程汇总
git·myeclipse·xmind
森林古猿12 小时前
再论斜率优化
c++·学习·算法
心中有国也有家2 小时前
鸿蒙Flutter开发环境从零搭建教程(Windows/macOS双平台·避坑版)
学习·flutter·华为·harmonyos
十月的皮皮4 小时前
C语言学习笔记20260706-栈的压入、弹出序列验证
c语言·笔记·学习
心中有国也有家4 小时前
Flutter 鸿蒙适配第一步:从 hive 迁移到 hive\_ce
hive·学习·flutter·华为·harmonyos
渣渣灰飞5 小时前
MySQL 系统学习 第二阶段 第三章 DQL(Data Query Language)第二节:WHERE 条件查询
sql·学习·mysql