Git

https://learngitbranching.js.org/?locale=zh_CN 学习笔记

git commit

store a version

现在你可以把提交记录看作是项目的快照

git branch

它们只是简单地指向某个提交纪录 —— 仅此而已

现在只要记住使用分支其实就相当于在说:“我想基于这个提交以及它所有的父提交进行新的工作。”

git merge

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

git rebase

Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

我们首先看一下 “HEAD”。 HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

HEAD 总是指向当前分支上最近一次提交记录

分离 HEAD

git checkout C1

相对引用

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

git checkout master^

git checkout HEAD~4

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

1
git branch -f master HEAD~3

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

相对引用为我们提供了一种简洁的引用提交记录 C1 的方式, 而 -f 则容许我们将分支强制移动到那个位置。

git reset

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

git reset HEAD~1

Git Revert

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!

为了撤销更改并分享给别人,我们需要使用 git revert

git revert HEAD

Git Cherry-pick

本系列的第一个命令是 git cherry-pick, 命令形式为:

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

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

交互式的 rebase

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

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

git rebase -i HEAD~4

只提取一个提交记录

  • git rebase -i
  • git cherry-pick

提交的技巧 #1 #2

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

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

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

  • 先用 git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前
  • 然后用 commit --amend 来进行一些小修改
  • 接着再用 git rebase -i 来将他们调回原来的顺序
  • 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!

git commit amend

当我们想要对上一次的提交进行修改时,我们可以使用git commit –amend命令。git commit –amend既可以对上次提交的内容进行修改,也可以修改提交说明。

git使用amend选项提供了最后一次commit的反悔。但是对于历史提交呢,就必须使用rebase了。

​ git rebase -i HEAD~3

​ 表示要修改当前版本的倒数第三次状态。

​ 这个命令出来之后,会出来三行东东:

​ pick:***

​ pick:***

​ pick:***

​ 如果你要修改哪个,就把那行的pick改成edit,然后退出。

​ 这时通过git log你可以发现,git的最后一次提交已经变成你选的那个了,这时再使用:

​ git commit –amend

​ 来对commit进行修改。

​ 修改完了之后,要回来对不对?

​ 使用git rebase –continue

​ OK,一切都搞定了。

Git Tags

Git 的 tag 就是干这个用的啊,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。

git tag v1 C1

我们将这个标签命名为 v1,并且明确地让它指向提交记录 C1,如果你不指定提交记录,Git 会用 HEAD 所指向的位置。

1
2
3
git tag v0 c1
git tag v1 c2
git checkout c2

Git Describe

由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe

Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用 git bisect(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。

git describe 的语法是:

1
git describe ref

ref 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会以你目前所检出的位置(HEAD)。

它输出的结果是这样的:

1
<tag>_<numCommits>_g<hash>

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

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

多分支 rebase

1
2
3
4
git rebase master bugFix
git rebase bugFix side
git rebase side another
git branch -f master another

git rebase master bugFix

get all commits bugFix indique and put them under master

git branch -f master another

move branch master to where another is

选择父提交记录

操作符 ^~ 符一样,后面也可以跟一个数字。

但是该操作符后面的数字与 ~ 后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的某个父提交。还记得前面提到过的一个合并提交有两个父提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。

Git 默认选择合并提交的“第一个”父提交,在操作符 ^ 后跟一个数字可以改变这一默认行为。

远程仓库

// TODO