对 git 的一些使用的笔记
对 git 的了解,仅限于对其概念,命令的了解是绝对不够的(实际上我现在也不能算了解),重要的是掌握相应的最佳实践。这里进行一些笔记。我对马上掌握 git 不抱任何期望——这玩意显然是应当在实践中掌握的。
纵览
一个 git 项目可以分为三部分——工作目录,暂存区,git 仓库。其中,工作目录代表项目某个版本提取出的内容(就像某时刻的快照——当前的也可以);git 仓库代表。git 目录下的内容,其是项目中最重要的部分,包括项目原数据以及对象数据库,从远程克隆仓库时,拷贝的就是 git 仓库的数据;暂存区是一个文件,保存下次提交时的文件列表信息。
git 的最简单的工作流程可以归纳如下——
- 克隆远程仓库(将会克隆整个 git 仓库的所有数据——这也就是说其会拉取每一个文件的所有版本到本地,而非仅当前所需要的文件)或初始化新仓库
- 修改文件
- 将文件的快照加入暂存区(
git add
命令) - 提交暂存区内容到仓库——这将生成永久性的快照(
git commit
命令)
在这个工作流程中,文件在各个阶段将会有不同状态,这取决于文件是否被追踪,修改是否已经暂存。
关于将修改加入到暂存区这一步,如果在文件 add 后再次编辑文件。文件将同时处于 Modified 和 Staged 状态——Staged 是编辑前被 add 的文件快照,Modified 是编辑后的文件,这时需再次执行 add 命令,但是旧的 add 命令的结果会被覆盖——如果需要保存该结果,应当在此时进行 commit。
git status -s
命令会紧凑地显示各被修改的文件的情况。其中,?? 代表未追踪,A 表示新添加到暂存区,左边的 M 表示文件修改且存入暂存区,右边的 M 表示文件修改且未存入暂存区。但这个或许没有必要了解——IDE 一般都提供了更丰富的表现方式。
1 |
|
git diff
命令将会显示当前尚未暂存文件和上一次提交/暂存文件的差别(未暂存的改动),git diff --staged
命令显示当前暂存文件和上一次提交文件的差别(已暂存的改动)。
git commit
命令将会把暂存区的快照进行提交并成为项目的一个快照(这个快照使能够完全回溯到项目的这个状态,快照是相对项目而言的,而非相对某个文件而言的;git 的版本控制指的是对项目的版本控制,而不是对各个文件的版本控制),在将来可以回退到该快照,或者进行比较等操作。也可以使用git commit -a
来一次提交所有跟踪过的文件,而不需要进行暂存。
分支
分支——把工作从开发主线上分离开来,以免影响开发主线。git 鼓励在工作流程中频繁使用分支和合并。这是说,最好在每次要进行修改的时候都创建新分支,进行编辑和测试后合并到原分支。也可以说,分支的目的是为了更好的合并。
这分支图一定是分分合合的。git 的默认分支(同时一般也是“主干”)的名字是 master,git init
默认会创建名为 master 的分支。
创建和切换分支
分支的实质是一个可以移动的指针,其能够指向任意一个快照。每次提交都会形成项目的一个快照,而创建新分支的操作则是创建一个可移动的指针引用当前快照,而进行提交(commit)时,提交的快照则会从这里进行分支,同时指针也会移动。创建新分支的命令是git branch <name>
。
如,下图使用git branch testing
命令创建了一个新分支,这个分支和 master 指向同一个快照(下面称为操作对象)。这里的 HEAD 也指向一个分支——当前的本地分支,在这里是 master,创建分支时不会改变当前分支。
HEAD 分支可以直接引用操作对象吗?
图片中的箭头代表包含指针指向对象。每一个对象都有一个指针让它能够引用它的父对象。
git checkout <branchname>
命令使能够切换分支(这里的<branchname>
也可以为操作对象)。
切换分支时,HEAD 会指向切换后的分支,同时工作目录的内容变为切换后分支的快照内容。在上面的例子里,如果这时进行编辑和提交,前后的分支就指向不同操作对象了。这时候再对前面的分支进行提交,就产生了分叉。
分支可以通过git branch -f <branchname> <target>
进行强制的移动。target 可以为相对路径,也可以为绝对路径。
关于对分支的使用,一般来说可以遵循这样的流程(就像 add,commit,push 这样的流程一样)——
- 为实现某需求,创建一个分支
- 在该分支上进行工作
- 完成工作后,合并分支到主分支
合并分支
合并操作显然是一个非常重要的部分。合并使用git merge <branchname>
命令。合并时会将当前的分支和待合并的分支进行合并——在这里,当前的分支的指针会移动,而待合并的分支指针不动。
下面是一个示例,在 C1 时,项目进行了分支以进行 bug 的修复,现在修复完了,而 main 分支也进行了更新,现在如何将 bugFix 的改动合并到当前的 main 分支上呢?
答案是将当前分支设为 main,并进行 merge 操作,具体命令如下——
1 |
|
最终会达到这样的结果——可以看到 bugFix 指针并未移动,main 则移动了。可见,main 是这次合并的主体,它把 bugFix 的内容融合进自己,让自己演进了。在进行合并操作时,应按照这样的语义来选择合并的主体。
git rebase
也能够进行合并操作,它的作用就如其名——转移父对象,就是更改当前指针的父对象。其能造成更加线性的提交历史。
下面是一个示例,展示了执行下面命令的前后状态。
1 |
|
可以看到,bugFix 的父对象成为 main 了。现在只需要移动 main 到新节点即可。
远程仓库
对远程仓库进行各种操作是 git 使用中不可或缺的部分。一个 git 仓库可以有多个远程仓库。
git remote [-v | --verbose]
命令允许对项目的远程仓库进行查看,其中-v
将会显示更详细的信息。
1 |
|
Continued…
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议 ,转载请注明出处!