版本控制-git-LearnGitBranching-主要
本文来源于LearnGitBranching官网
基础篇
git commit
Git 仓库中的提交记录保存的是你的目录下所有文件的快照
Git 将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录
Git 保存了提交的历史记录
|
|
在当前HEAD所在提交新建一个提交
git branch
Git 的分支简单地指向某个提交节点
早建分支!多用分支!
创建再多的分支也不会造成储存或内存上的开销,按逻辑分解工作到不同的分支要比维护特别臃肿的分支简单多了。
创建xxx分支
|
|
切换分支
|
|
分支与合并
git merge
|
|
此命令会将当前HEAD指向的分支的提交和xxx分支的提交合并生成一个新的提交,然后将当前HEAD指向的分支指向新的提交
git rebase
|
|
将当前分支
到当前分支和被合并分支xxx的公共祖先
的一系列提交放到被合并分支的下面
高级篇
在提交树上移动
HEAD 是当前提交记录的符号引用。
commit之后,HEAD 会指向新的提交记录。
HEAD 可以指向分支名(如 bugFix),这种情况下提交,会使 bugFix 也指向新的提交记录。
分离的 HEAD
分离的 HEAD 指向了具体的提交记录而不是分支名。
|
|
xxx为具体提交的hash值
相对引用
git log 来查查看当前分支提交记录的哈希值,需要找被丢弃的提交时可以通过git reflog查看所有执行过的命令
哈希值基于 SHA-1,共 40 位
只需要提供能够唯一标识提交记录的前几个字符(比如4个)即可
除了使用hash值的绝对引用提交外, Git 还引入了基于某一提交的相对引用提交
- 使用 ^ 向上移动 1 个提交记录:
git checkout xxx^
- 使用 ~ 向上移动多个提交记录,如 ~3:
git checkout xxx~4
使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:git branch -f main HEAD~3
撤销变更
Git Reset
|
|
git reset 通过把分支回退几个提交来实现撤销改动
此时向远程仓库推送会出错,如果一定要推送则使用-f选项
本地的reset并不会删除,添加–hard后会删除未使用分支
Git Revert
|
|
git revert 会在HEAD提交上创建一个新的提交,该提交和xxx的状态一样
移动提交记录
整理提交记录
本系列的第一个命令是 git cherry-pick, 命令形式为:
|
|
将一些提交复制到当前所在的位置(HEAD)下面
该命令与rebase的区别是cherry-pick不会将rebase的祖先提交也复制到HEAD指向的提交后面,而是只拿你选中的提交
交互式的 rebase
交互式 rebase 指的是使用带参数 –interactive 的 rebase 命令, 简写为 -i。 Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明。
当 rebase UI界面打开时, 你能做3件事:
- 调整提交记录的顺序(通过鼠标拖放来完成)
- 删除你不想要的提交(通过切换 pick 的状态来完成,关闭就意味着你不想要这个提交记录)
- 合并提交。 遗憾的是由于某种逻辑的原因,我们的课程不支持此功能,因此我不会详细介绍这个操作。简而言之,它允许你把多个提交记录合并成一个。
杂项
本地栈式提交
来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。
这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!
最后就差把 bugFix 分支里的工作合并回 main 分支了。你可以选择通过 fast-forward 快速合并到 main 分支上,但这样的话 main 分支就会包含我这些调试语句了。你肯定不想这样,应该还有更好的方式
实际我们只要让 Git 复制解决问题的那一个提交记录就可以了。跟之前我们在“整理提交记录”中学到的一样,我们可以使用
- git rebase -i
- git cherry-pick
提交的技巧 #1
接下来这种情况也是很常见的:你之前在 newImage 分支上进行了一次提交,然后又基于它创建了 caption 分支,然后又提交了一次。
此时你想对某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。
我们可以通过下面的方法来克服困难:
- 先用 git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前
- 然后用 git commit –amend 来进行一些小修改,这个命令会用当前暂存区的内容覆盖当前的提交
- 接着再用 git rebase -i 来将他们调回原来的顺序
- 最后我们把 main 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!
提交的技巧 #2
正如你在上一关所见到的,我们可以使用 rebase -i 对提交记录进行重新排序。只要把我们想要的提交记录挪到最前端,我们就可以很轻松的用 –amend 修改它,然后把它们重新排成我们想要的顺序。
但这样做就唯一的问题就是要进行两次排序,而这有可能造成由 rebase 而导致的冲突。下面还是看看 git cherry-pick 是怎么做的吧。
要在心里牢记 cherry-pick 可以将提交树上任何地方的提交记录取过来追加到 HEAD 上(只要不是 HEAD 上游的提交就没问题)。
这一关的目标和上一关一样,通过 –amend 改变提交记录 C2,但你不能用 rebase -i。
Git Tags
Git 的 tag 可以将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。
|
|
我们将这个标签命名为 v1,并且明确地让它指向提交记录 C1,如果不指定提交记录,Git 会用 HEAD 所指向的位置。
Git Describe
git describe描述离你最近的锚点(也就是标签)
|
|
<ref>
可以是任何能被 Git 识别成提交记录的引用,如果没有指定,Git 会以目前所检出的位置(HEAD)。
输出的结果是这样的:<tag>_<numCommits>_g<hash>
tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。
当 ref 提交记录上有某个标签时,则只输出标签名称
高级话题
多次rebase
选择父提交记录
操作符 ^ 与 ~ 符一样,后面也可以跟一个数字。
指定merge合并提交记录的某个父提交。还记得前面提到过的一个合并提交有两个父提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。
Git 默认选择合并提交的“第一个”父提交,在操作符 ^ 后跟一个数字可以改变这一默认行为。