Git学习(二)

一、版本管理

1.1 撤销修改

git commit --amend
这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。
例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:

$ git commit -m ‘initial commit’
$ git add forgotten_file
$ git commit --amend

最终你只会有一个提交——第二次提交将代替第一次提交的结果。

当你在修补最后的提交时,并不是通过用改进后的提交 原位替换 掉旧有提交的方式来修复的, 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。

取消暂存

$ git reset HEAD readme.txt

撤销修改

$ git checkout – readme.txt

1.2 删除文件

rm test.txt

此时,工作区和版本库就不一致了

$ git rm test.txt
rm ‘test.txt’

$ git commit -m “remove test.txt”

现在,文件就从版本库中被删除了。

小提示:先手动删除文件,然后使用git rm 和git add效果是一样的。

$ git checkout – test.txt

一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本

如果从来没提交到版本库,是没法还原

1.3 小结

  • 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

  • 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作

  • 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,可以用命令git reset --hard commit_id,不过前提是没有推送到远程库

二、分支管理

2.1 git 分支原理

假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。
Git 仓库对象变化详解:

现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)。

在这里插入图片描述

做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。

在这里插入图片描述

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 master 分支会在每次提交时自动向前移动。

在这里插入图片描述
在 Git 里,每个仓库都会有一个主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git 用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
在这里插入图片描述

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

当我们创建新的分支,例如dev时,Git 新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
在这里插入图片描述

你看,Git 创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
在这里插入图片描述
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git 怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
在这里插入图片描述

所以 Git 合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

在这里插入图片描述

2.2 修改不同的分支

2.2.1 创建分支

首先,我们创建dev分支,然后切换到dev分支

$ git checkout -b dev
Switched to a new branch ‘dev’

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

$ git branch dev
$ git checkout dev
Switched to branch ‘dev’

在这里插入图片描述

2.2.1 查看当前分支

$ git branch

在这里插入图片描述
可以在dev分支上正常提交,比如对readme.txt做个修改,提交:

$ git add readme.txt
$ git commit -m “branch test”

在这里插入图片描述

dev分支的工作完成,我们就可以切换回master分支

$ git checkout master

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
在这里插入图片描述
在这里插入图片描述

2.3 git 合并分支

2.3.1 合并分支

现在,我们把dev分支的工作成果合并到master分支上:

$ git merge dev

在这里插入图片描述

2.3.2 删除分支

合并完成后,就可以放心地删除dev分支了:

$ git branch -d dev

在这里插入图片描述
查看
在这里插入图片描述

我们注意到切换分支使用git checkout <branch>,而 Git 中撤销修改则是git checkout -- <file>,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch更科学。因此,最新版本的 Git 提供了新的git switch命令来切换分支:
git switch

创建并切换到新的dev分支,可以使用:

$ git switch -c dev

直接切换到已有的master分支,可以使用:

$ git switch master

使用新的git switch命令,比git checkout要更容易理解。

2.4 git 合并策略

通常,合并分支时,如果可能,Git 会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git 就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
下面我们看一看--no-ff方式的git merge

$ git merge --no-ff -m “merge with no-ff” dev

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
合并后,我们用git log看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit

  • fc76cf7 (HEAD -> master) merge with no-ff
    |\
    | * f52c633 (dev) add merge
    |/
  • cf810e4 conflict fixed

可以看到,不使用Fast forward模式,merge后就像这样:
在这里插入图片描述

在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
其次,干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,并在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
在这里插入图片描述

2.5 实战(1): 准备新分支

$ git checkout -b dev

2.6 实战(2): 修改master分支

$ git checkout master

posted @ 2022-07-28 14:06  周末不下雨  阅读(11)  评论(0编辑  收藏  举报