图解Git

图解Git

Git是什么?

Git是目前世界上最先进的分布式版本控制系统。
工作原理 / 流程:

img

Workspace:工作区
Index / Stage:暂存区
Repository:仓库区(或本地仓库)
Remote:远程仓库

图解git命令

本地案例

git commit

功能:本地提交

详解:

Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但 比复制粘贴优雅许多!

Git 希望提交记录尽可能地轻量,因此在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情 况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。

Git 还保存了提交的历史记录。

mainc0c1 (main*)
mainc0c1c2 (main*)

git branch

功能:创建分支

详解:

Git 的分支也非常轻量。它们只是简单地指向某个提交纪录 —— 仅此而已。所以许多 Git 爱好者传颂:

早建分支!多用分支!

这是因为即使创建再多的分支也不会造成储存或内存上的开销,并且按逻辑分解工作到不同的分支要比维护那些特别臃肿的分支简单多了。

在将分支和提交记录结合起来后,我们会看到两者如何协作。

git branch <分支name>
mainc0c1 (main*)
mainnewImagec0c1 (main*,newImage)

接下来提交一次,会发现为什么 main 分支前进了,newImage` 分支还待在原地呢?!这是因为我们没有“在”这个新分支上,(*)表示当前所在分支。

mainnewImagec0c1 (newImage)c2 (main*)

我们想要切换到新的分支上,可以执行

git checkout <分支name>
//创建并切换分支
git checkout -b <your-branch-name>。
mainnewImagec0c1c2 (main)c3(newImage*)

注意:在 Git 2.23 版本中,引入了一个名为 git switch 的新命令,最终会取代 git checkout,因为 checkout 作为单个命令有点超载(它承载了很多独立的功能)。

git merge

功能:合并分支

详解:

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

mainnewImagec0c1c2(main*)c3(newImage)

main 现在指向了一个拥有两个 parent 节点的提交记录。假如从 main 开始沿着箭头向上看,在到达起点的路上会经过所有的提交记录。这意味着 main 包含了对代码库的所有修改。↓↓↓

mainnewImagec0c1c2c3c4(main*,newImage)

git rebase

功能:合并分支(和merge做对比)

详解:Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

mainnewImagec0c1c2c3c3'(newImage,main*)

功能:当前指向

详解:

HEAD 是一个对当前所在分支的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。

mainc0c1 (main)(HEAD)

像这样HEAD就指向了c1节点(而不是main分支),当提交之后就只有HEAD向前移动了

mainc0c1 (main)c2(HEAD)

对比(注意图中的"*"号,main分支有说明HEAD在main上而不是节点上)

mainc0c1c2(main,HEAD)
  • 使用 ^ 向上移动 1 个提交记录
  • 使用 ~ 向上移动多个提交记录,如 ~3

git reset

功能:本地撤销更改

详解:git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。

mainc0c1c2(main*)
git reset HEAD^
mainc0c1(main*)c2

git revert

功能:撤销更改

详解:

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!为了撤销更改并分享给别人,我们需要使用 git revert

mainc0c1c2c2'(main*)

git cherry-pick

功能:复制

详解:

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

  • git cherry-pick <提交号>...
mainsidec0c1c2c3c4c5c6cherry-pick:c4cherry-pick:c6

git rebase

功能:复制(对比cherry-pick)并且可以调节顺序

详解:

当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了 —— 没有比这更简单的方式了。但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase —— 如果你想从一系列的提交记录中找到想要的记录, 这就是最好的方法了

交互式 rebase 指的是使用带参数 --interactive 的 rebase 命令, 简写为 -i如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。

git rebase -i <分支名/HEAD/节点哈希>
mainsidec0c1c23-1d3ad3d4-e6edbcf5-11e38ab
git rebase -i <side/HEAD~3/3-.. 5.. 4..>
mainsidec0c1c2c3c4c5c3'c5'c4'(main*)

git tag

功能:控制版本

详解:

永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。更难得的是,它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。

git tag <标签> <指定记录/HEAD>
git tag v1 c1
mainc0c11.0c2(main*)

远程案例

远程仓库

概念:

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

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

远程分支

概念:

我们的本地仓库多了一个名为 o/main 的分支, 这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性。远程分支反映了远程仓库(在你上次和它通信时)的状态。这会有助于你理解本地的工作与公共工作的差别 —— 这是你与别人分享工作成果前至关重要的一步.远程分支有一个特别的属性,在你切换到远程分支时,自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果。

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

<remote name>/<branch name>

因此,如果你看到一个名为 o/main 的分支,那么这个分支就叫 main,远程仓库的名称就是 o。大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了;不过 origin 对于我们的 UI 来说太长了,因此不得不使用简写 o 😃 但是要记住, 当你使用真正的 Git 时, 你的远程仓库默认为 origin!

git clone

功能:克隆远程仓库到本地

git fetch

功能:从远程仓库获取数据

详解:

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

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

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

远程分支反映了远程仓库在你最后一次与它通信时的状态,git fetch 就是你与远程仓库通信的方式了!

git fetch 通常通过互联网(使用 http://git:// 协议) 与远程仓库通信。

git fetch 并不会改变你本地仓库的状态。它不会更新你的 main 分支,也不会修改你磁盘上的文件。你可以将 git fetch 的理解为单纯的下载操作。

远程仓库

mainc0c1c2c3(main*)

本地仓库:C2,C3 被下载到了本地仓库,同时远程分支 o/main 也被更新

mainc0c1(main*)c2c3(o/main)

参数:

//拉取具体的资源
git fetch <remote> <place>
//拉取远程foo分支到本地o/foo分支,没有新建
EX:git fetch origin foo
//拉取具体的资源到本地具体分支
git fetch <remote> <source>:<destination>
//拉取远程foo分支到本地main分支,没有新建
EX:git fetch origin foo/main
//没有source属性,新增本地foo分支
git fetch origin :foo

git pull

功能:更新并合并远程记录到本地

详解:

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

本地仓库:

mainc0c1c2c3(main*,o/main)

git push

功能:提交本地变更到远程仓库

详解:

git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。一旦 git push 完成, 你的朋友们就可以从这个远程仓库下载你分享的成果了!

远程仓库:

mainc0c1c2c3(main*)

本地仓库:远程仓库接收了 C2,c3,远程仓库中的 main 分支也被更新到指向 C3 了,我们的远程分支 (o/main) 也同样被更新了。所有的分支都同步了!

mainc0c1c2c3(main*,o/main)

参数:

git push <remote> <place>
<!--切到本地仓库中的“main”分支,获取所有的提交,再到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去,同步的两个仓库的位置。 -->
EX:git push origin main
//推送至具体资源到远程具体资源分支下,没有将会新建
git push origin <source>:<destination>
//将本地仓库side分支推送至远程main分支
EX:git push origin side:main
//没有source属性,删除远程foo分支
git push origin :foo

动画演示地址:https://learngitbranching.js.org/

posted @   是秃子总会发光^_^  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示