Skip to content

git原理解析 #3

@liang520

Description

@liang520

理解

  1. Git 仓库中的提交记录保存的是你的目录下所有文件的“快照”,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅许多!
  2. 在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的“差异“打包到一起作为一个提交记录。
  3. Git 还保存了提交的“历史记录”。这也是为什么大多数提交记录的上面都有”父节点“的原因

git commit
初始提交 C0 和其后可能包含某些有用修改的提交 C1。(*号表示当前所在分支)
image
执行git commit之后,基于C1修改保存成提交记录C2;
image

git Branch
分支非常轻量。它们只是简单地指向某个提交纪录--仅此而已。
因为即使创建再多分的支也不会造成储存或内存上的开销,并且按逻辑分解工作到不同的分支要比维护那些特别臃肿的分支简单多了。
只要记住使用分支其实就相当于在说:“我想基于这个提交以及它所有的父提交进行新的工作。”
如图创建新的newImage分支放入过程
image
执行git branch newImage
image
git checkout newImage;git commit切换到新分支,基于当前分支提交代码
image

创建新分支并切换到新分支git checkout -b <your-branch-name>

分支与合并
第一种方法:git merge ,合并两个分支时会产生一个特殊的提交记录,它有两个父节点;
把 bugFix 合并到 master 里
image
git merge bugFix
image
再把 master 分支合并到 bugFix:git checkout bugFix;git merge master
image
master 继承自 bugFix,Git 什么都不用做,只是简单地把 bugFix 移动到 master 所指向的那个提交记录。

git rebase
rebase也是一种合并方法,Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
准备了两个分支;注意当前所在的分支是 bugFix(星号标识的是当前分支)
image
把 bugFix 分支里的工作直接移到 master 分支上。移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的。
执行git rebase master
image
注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 master 分支上的 C3 的副本。
再更新master,切换到master分支;
image
把它 rebase 到 bugFix 分支上
2018-11-30 1 10 13
由于 bugFix 继承自 master,所以 Git 只是简单的把 master 分支的引用向前移动了一下而已。

在提交树上面移动
HEAD: HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。HEAD 总是指向当前分支上最近一次提交记录。
观察提交前后 HEAD 的位置。
image
执行git checkout C1;git checkout master;git commit;git checkout C2;
ko4fz-ta1lz
如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看, 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向。

分离HEAD
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名;
如图,在命令执行之前的状态如下所示:
HEAD -> master -> C1
HEAD 指向 master, master 指向 C1
image
执行git checkout C1命令
image
现在变成了 HEAD -> C1

相对引用
通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,所以你就不得不用 git log 来查查看提交记录的哈希值。通过哈希值指定提交记录很不方便,所以 Git 引入了相对引用。
使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。
两个简单的用法:

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

首先看看操作符 (^)。把这个符号加在引用名称的后面,表示让 Git 寻找指定提交记录的父提交。
所以 master^ 相当于“master 的父节点”。
master^^ 是 master 的第二个父节点
image
执行git checkout master^
image

使用~ 一次后退四步,例如:
image
执行git checkout HEAD~4
image

强制修改分支位置
相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。
git branch -f master HEAD~3
image
上面的命令会将 master 分支强制指向 HEAD 的第 3 级父提交。
image
-f 则容许我们将分支强制移动到那个位置。

撤销变更
主要有两种方法用来撤销变更 —— 一是 git reset,还有就是 git revert。

git reset 通过把分支记录回退几个提交记录来实现撤销改动。
image
执行git reset HEAD~1
image
在reset后, C2 所做的变更还在,但是处于未加入暂存区状态,reset对于本地分支很方便,对于远程分支是无效的

使用git revert ,为了撤销更改并分享给别人;
image
执行git revert HEAD
image
C2' 的状态与 C1 是相同的。

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

git cherry-pick <提交号>...
image
执行git cherry-pick C2 C4
image

例一种方法,git rebase -i HEAD~4弹出交互框,手动选择性的拖拽合并

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions